Re: [Freedreno] [PATCH v2 4/7] drm/msm/dpu: allow just single IRQ callback
one> On 2021-08-17 20:30, abhin...@codeaurora.org wrote: On 2021-06-17 15:20, Dmitry Baryshkov wrote: DPU interrupts code allows multiple callbacks per interrut. In reality /interrupt none of the interrupts is shared between blocks (and will probably never be). Drop support for registering multiple callbacks per interrupt to simplify interrupt handling code. Signed-off-by: Dmitry Baryshkov I need to check on why we had this design originally and we still do. the idx with which we are registering today can generate only one hw interrupt. But i am not sure if something for planned for future use. Will update in a day or two. meanwhile some comments and questions below. I did check internally on the original design of this and yes the plan was for other sub-modules to register for callbacks and that callback goes into the callback list. For example, lets say for some reason some other modules like the DSI want to register for the VSYNC interrupt, it can register for a callback and that will get added to the callback list. But, this never got used that way and even now there is only one callback per interrupt. We dont have a concrete use-case where we will need this in the future but like many other things, we cannot tell for certain. Since there is no concrete use-case where we might need this, if you would like to go ahead with this, please do. Once you address the other comments on this, I can ack this. --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h | 18 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 6 +- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 2 +- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 10 +- .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 6 +- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 144 +++--- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 12 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 12 -- drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 10 +- 9 files changed, 86 insertions(+), 134 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h index 90ae6c9ccc95..44ab97fb2964 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h @@ -46,10 +46,8 @@ u32 dpu_core_irq_read( * interrupt * @dpu_kms: DPU handle * @irq_idx: irq index - * @irq_cb:IRQ callback structure, containing callback function - * and argument. Passing NULL for irq_cb will unregister - * the callback for the given irq_idx - * This must exist until un-registration. + * @irq_cb:IRQ callback funcion. + * @irq_arg: IRQ callback argument. * @return:0 for success registering callback, otherwise failure * * This function supports registration of multiple callbacks for each interrupt. @@ -57,17 +55,16 @@ u32 dpu_core_irq_read( int dpu_core_irq_register_callback( struct dpu_kms *dpu_kms, int irq_idx, - struct dpu_irq_callback *irq_cb); + void (*irq_cb)(void *arg, int irq_idx), + void *irq_arg); /** * dpu_core_irq_unregister_callback - For unregistering callback function on IRQ * interrupt * @dpu_kms: DPU handle * @irq_idx: irq index - * @irq_cb:IRQ callback structure, containing callback function - * and argument. Passing NULL for irq_cb will unregister - * the callback for the given irq_idx - * This must match with registration. + * @irq_cb:IRQ callback funcion. /function this typo is there in multiple places + * @irq_arg: IRQ callback argument. * @return:0 for success registering callback, otherwise failure * * This function supports registration of multiple callbacks for each interrupt. @@ -75,7 +72,8 @@ int dpu_core_irq_register_callback( int dpu_core_irq_unregister_callback( struct dpu_kms *dpu_kms, int irq_idx, - struct dpu_irq_callback *irq_cb); + void (*irq_cb)(void *arg, int irq_idx), + void *irq_arg); /** * dpu_debugfs_core_irq_init - register core irq debugfs diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 1c04b7cce43e..d3557b0f4db9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -310,7 +310,7 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); local_irq_save(flags); - irq->cb.func(phys_enc, irq->irq_idx);
Re: [Freedreno] [PATCH] drm/msm/dp: Move debugfs files into subdirectory
On 2021-10-18 11:36, Bjorn Andersson wrote: On Mon 18 Oct 11:07 PDT 2021, abhin...@codeaurora.org wrote: Hi Bjorn On 2021-10-17 09:42, Bjorn Andersson wrote: > On Fri 15 Oct 16:53 PDT 2021, abhin...@codeaurora.org wrote: > > > On 2021-10-15 16:17, Bjorn Andersson wrote: > > > In the cleanup path of the MSM DP driver the DP driver's debugfs files > > > are destroyed by invoking debugfs_remove_recursive() on debug->root, > > > which during initialization has been set to minor->debugfs_root. > > > > > > To allow cleaning up the DP driver's debugfs files either each dentry > > > needs to be kept track of or the files needs to be put in a subdirectory > > > which can be removed in one go. > > > > > > By choosing to put the debugfs files in a subdirectory, based on the > > > name of the associated connector this also solves the problem that these > > > names would collide as support for multiple DP instances are introduced. > > > > > > One alternative solution to the problem with colliding file names would > > > have been to put keep track of the individual files and put them under > > > the connector's debugfs directory. But while the drm_connector has been > > > allocated, its associated debugfs directory has not been created at the > > > time of initialization of the dp_debug. > > > > > > Signed-off-by: Bjorn Andersson > > > > I have been thinking about this problem ever since multi-DP has been > > posted > > :) > > Creating sub-directories seems right but at the moment it looks like > > IGT > > which > > uses these debugfs nodes doesnt check sub-directories: > > > > https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/blob/master/tools/msm_dp_compliance.c#L215 > > > > It looks for the DP debugfs nodes under /sys/kernel/debug/dri/*/ > > > > We have to fix IGT too to be able to handle multi-DP cases. I will > > try to > > come up > > with a proposal to address this. > > > > Till then, can we go with the other solution to keep track of the > > dentries? > > > > I'm afraid I don't see what you're proposing. > > Afaict we need one set of dp_test{type,active,data} per DP controller, > so even doing this by keeping track of the dentries requires that we > rename the files based on some identifier (id or connector name) - which > will cause igt to break. Yes, I also thought the same that there needs to be some identifier. "To allow cleaning up the DP driver's debugfs files either each dentry needs to be kept track of or the files needs to be put in a subdirectory which can be removed in one go" I guess I misunderstood your statement in the commit text thinking that you had some other way to keep track of the dentries as it mentioned that use a subdirectory OR keep track of each dentry. No, I did write that code as well and then ditched it. Unfortunately I don't think it would help you, because we still need to add some identifier to the file names and preferably we should add that to the single case as well to make things consistent. > > As such, I think the practical path forward is that we merge the > multi-DP series as currently proposed. This will not cause any issues on > single-DP systems, but on multi-DP systems we will have warnings about > duplicate debugfs entries in the kernel logs. > > Then you can figure out how to rework igt to deal with the multiple DP > instances and update the dp_debug interface accordingly. > Fine with me, I will take care of this. Cool, thanks. Regards, Bjorn Following up on this, Rob has posted the igt change today which i acked. https://patchwork.freedesktop.org/patch/465930/ With this in place, we can actually go ahead with this change. Hence, Reviewed-by: Abhinav Kumar > > Which also implies that we should hold this patch back. But if we go > that path, I think we should fix dp_debug_deinit() so that it doesn't > remove /sys/kernel/debug/dri/128 when the DP driver is unloaded. Yes, lets hold this patch back till I fix multi-DP for IGT. > > Regards, > Bjorn > > > > --- > > > > > > This depends on > > > https://lore.kernel.org/linux-arm-msm/20211010030435.4000642-1-bjorn.anders...@linaro.org/ > > > reducing the connector from a double pointer. > > > > > > drivers/gpu/drm/msm/dp/dp_debug.c | 15 +-- > > > 1 file changed, 9 insertions(+), 6 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c > > > b/drivers/gpu/drm/msm/dp/dp_debug.c > > > index da4323556ef3..67da4c69eca1 100644 > > > --- a/drivers/gpu/drm/msm/dp/dp_debug.c > > > +++ b/drivers/gpu/drm/msm/dp/dp_debug.c > > > @@ -210,26 +210,29 @@ static const struct file_operations > > > test_active_fops = { > > > static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor > > > *minor) > > > { > > > int rc = 0; > > > +char path[64]; > > > struct dp_debug_private *debug = container_of(dp_debug, > > > struct dp_debug_private, dp_debug); > > > > > > -debugfs_create_file("dp_debug", 0444,
Re: [Freedreno] [PATCH v2 22/22] drm/msm/dpu: add multirect support
On 2021-07-04 18:21, Dmitry Baryshkov wrote: If SmartDMA is supported by the hardware, SSPPs allow using two RGB layers per the hardware pipe (with some additional restrictions, like no support for scaling, etc). Register additional planes (two per the SSPP) and check if we can use multirect during atomic_check. I can see you are still making use of the dpu_rm_get_sspp() function to allocate SSPPs for the drm planes even in the case of smart dma. That function doesnt account for the foll considerations: 1) How does it guarantee plane priority while allocation? smart dma planes need to be allocated in a priority order and that priority order decides which sspp does on the left rectangle and which one on the right. I am not seeing how that is enforced in this implementation. 2) Another condition to be taken into account is that if one rectangle of one SSPP is utilized for one display, the other rectangle of the SSPP cannot be used for another display. How is this guaranteed? Does the RM global state account for this? Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 18 +++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 109 +- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 29 +- 4 files changed, 86 insertions(+), 72 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 49bdd5953b9f..49bd9df387b8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -892,7 +892,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, struct dpu_global_state *global_state = dpu_kms_get_global_state(state); struct dpu_plane_state **pstates; - struct dpu_plane_state *pstate; + struct dpu_plane_state *pstate, *prev_plane_state; struct drm_plane_state *plane_state; struct drm_plane *plane; @@ -962,6 +962,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, } stage = DPU_STAGE_0; + prev_plane_state = NULL; for (i = 0; i <= max_zpos; i++) { pstate = pstates[i]; if (!pstate) @@ -977,8 +978,6 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, plane_state = >base; - dpu_plane_clear_multirect(plane_state); - dst = drm_plane_state_dest(plane_state); if (!drm_rect_intersect(, _rect)) { DPU_ERROR("invalid vertical/horizontal destination\n"); @@ -990,7 +989,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, } plane = pstate->base.plane; - rc = dpu_plane_set_pipe(plane, pstate); + rc = dpu_plane_set_pipe(plane, pstate, prev_plane_state); if (rc) { DPU_ERROR("%s: error setting pipe for %s\n", dpu_crtc->name, plane->name); goto end; @@ -1002,6 +1001,17 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, goto end; } + /* +* If this plane was not selected for multirect, so we can try +* using it together with the next pipe. If it selected for +* the REC1, next pipe will have to start from REC_SOLO (and +* maybe be promoted to REC0 later. +*/ + if (pstate->multirect_index == DPU_SSPP_RECT_SOLO) + prev_plane_state = pstate; + else + prev_plane_state = NULL; + pstates[i]->stage = stage++; DRM_DEBUG_ATOMIC("%s: stage %d\n", dpu_crtc->name, stage); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 08a7e56cc98f..c3c3972627ca 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -646,7 +646,7 @@ static int _dpu_kms_create_planes_virtual(struct dpu_kms *dpu_kms, int max_crtc_ catalog = dpu_kms->catalog; /* Create the planes, keeping track of one primary/cursor per crtc */ - for (i = 0; i < catalog->sspp_count; i++) { + for (i = 0; i < 2 * catalog->sspp_count; i++) { enum drm_plane_type type; if (primary_planes_idx < max_crtc_count) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 420cdd90e89b..77cb4f172379 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -292,10 +292,10 @@ static u64 _dpu_plane_get_qos_lut(const struct dpu_qos_lut_tbl *tbl, * _dpu_plane_set_qos_lut - set QoS LUT of the given plane * @plane: Pointer to drm plane * @fb:Pointer to framebuffer associated with the given plane - * @pipe_cfg: Pointer
Re: [Freedreno] [PATCH v2 21/22] drm/msm/dpu: fix CDP setup to account for multirect index
On 2021-07-04 18:21, Dmitry Baryshkov wrote: Client driven prefetch (CDP) is properly setup only for SSPP REC0 currently. Enable client driven prefetch also for SSPP REC1. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 12 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 4 +++- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c index f93cdeb08ac7..96f2f3f12f34 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c @@ -75,6 +75,7 @@ #define SSPP_TRAFFIC_SHAPER0x130 #define SSPP_CDP_CNTL 0x134 #define SSPP_UBWC_ERROR_STATUS 0x138 +#define SSPP_CDP_CNTL_REC1 0x13c #define SSPP_TRAFFIC_SHAPER_PREFILL0x150 #define SSPP_TRAFFIC_SHAPER_REC1_PREFILL 0x154 #define SSPP_TRAFFIC_SHAPER_REC1 0x158 @@ -624,10 +625,12 @@ static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_pipe *ctx, } static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx, - struct dpu_hw_pipe_cdp_cfg *cfg) + struct dpu_hw_pipe_cdp_cfg *cfg, + enum dpu_sspp_multirect_index index) { u32 idx; u32 cdp_cntl = 0; + u32 cdp_cntl_offset = 0; if (!ctx || !cfg) return; @@ -635,6 +638,11 @@ static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx, if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, )) return; + if (index == DPU_SSPP_RECT_SOLO || index == DPU_SSPP_RECT_0) + cdp_cntl_offset = SSPP_CDP_CNTL; + else + cdp_cntl_offset = SSPP_CDP_CNTL_REC1; + if (cfg->enable) cdp_cntl |= BIT(0); if (cfg->ubwc_meta_enable) @@ -644,7 +652,7 @@ static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx, if (cfg->preload_ahead == DPU_SSPP_CDP_PRELOAD_AHEAD_64) cdp_cntl |= BIT(3); - DPU_REG_WRITE(>hw, SSPP_CDP_CNTL, cdp_cntl); + DPU_REG_WRITE(>hw, cdp_cntl_offset, cdp_cntl); } static void _setup_layer_ops(struct dpu_hw_pipe *c, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h index c5ac8defa073..19c5358b962c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h @@ -358,9 +358,11 @@ struct dpu_hw_sspp_ops { * setup_cdp - setup client driven prefetch * @ctx: Pointer to pipe context * @cfg: Pointer to cdp configuration +* @index: rectangle index in multirect */ void (*setup_cdp)(struct dpu_hw_pipe *ctx, - struct dpu_hw_pipe_cdp_cfg *cfg); + struct dpu_hw_pipe_cdp_cfg *cfg, + enum dpu_sspp_multirect_index index); }; /** diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index d692136884ad..420cdd90e89b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -1241,7 +1241,7 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) DPU_FORMAT_IS_TILE(fmt); cdp_cfg.preload_ahead = DPU_SSPP_CDP_PRELOAD_AHEAD_64; - pstate->pipe_hw->ops.setup_cdp(pstate->pipe_hw, _cfg); + pstate->pipe_hw->ops.setup_cdp(pstate->pipe_hw, _cfg, pstate->multirect_index); } }
Re: [Freedreno] [PATCH v2 20/22] drm/msm/dpu: fix smart dma support
On 2021-07-04 18:21, Dmitry Baryshkov wrote: Downstream driver uses dpu->caps->smart_dma_rev to update sspp->cap->features with the bit corresponding to the supported SmartDMA version. Upstream driver does not do this, resulting in SSPP subdriver not enbaling setup_multirect callback. Make SSPP subdriver check global smart_dma_rev to decide if setup_multirect should be enabled. Signed-off-by: Dmitry Baryshkov Instead of this approach, we can OR the DPU_SSPP_SMART_DMA_* to the features list? --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 10 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 16 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c| 9 + 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index b8e0fece1f0b..d2321648b8d2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -185,7 +185,7 @@ static const struct dpu_caps sdm845_dpu_caps = { .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .qseed_type = DPU_SSPP_SCALER_QSEED3, - .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, + .smart_dma_rev = DPU_SMART_DMA_V2, .ubwc_version = DPU_HW_UBWC_VER_20, .has_src_split = true, .has_dim_layer = true, @@ -203,7 +203,7 @@ static const struct dpu_caps sc7180_dpu_caps = { .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0x9, .qseed_type = DPU_SSPP_SCALER_QSEED4, - .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, + .smart_dma_rev = DPU_SMART_DMA_V2, .ubwc_version = DPU_HW_UBWC_VER_20, .has_dim_layer = true, .has_idle_pc = true, @@ -217,7 +217,7 @@ static const struct dpu_caps sm8150_dpu_caps = { .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .qseed_type = DPU_SSPP_SCALER_QSEED3, - .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */ + .smart_dma_rev = DPU_SMART_DMA_V2, /* TODO: v2.5 */ .ubwc_version = DPU_HW_UBWC_VER_30, .has_src_split = true, .has_dim_layer = true, @@ -235,7 +235,7 @@ static const struct dpu_caps sm8250_dpu_caps = { .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .qseed_type = DPU_SSPP_SCALER_QSEED3LITE, - .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */ + .smart_dma_rev = DPU_SMART_DMA_V2, /* TODO: v2.5 */ .ubwc_version = DPU_HW_UBWC_VER_40, .has_src_split = true, .has_dim_layer = true, @@ -251,7 +251,7 @@ static const struct dpu_caps sc7280_dpu_caps = { .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0x7, .qseed_type = DPU_SSPP_SCALER_QSEED4, - .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, + .smart_dma_rev = DPU_SMART_DMA_V2, .ubwc_version = DPU_HW_UBWC_VER_30, .has_dim_layer = true, .has_idle_pc = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index f3c5aa3f4b3f..66d7b43c0019 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -70,6 +70,18 @@ enum { DPU_HW_UBWC_VER_40 = 0x400, }; +/** + * SmartDMA support + * @DPU_SMART_DMA_UNSUPPORTED, SmartDMA not support + * @DPU_SMART_DMA_V1, SmartDMA 1.0 support + * @DPU_SMART_DMA_V2, SmartDMA 2.0 support + */ +enum { + DPU_SMART_DMA_UNSUPPORTED, + DPU_SMART_DMA_V1, + DPU_SMART_DMA_V2, +}; + /** * MDP TOP BLOCK features * @DPU_MDP_PANIC_PER_PIPE Panic configuration needs to be be done per pipe @@ -104,8 +116,6 @@ enum { * @DPU_SSPP_QOS,SSPP support QoS control, danger/safe/creq * @DPU_SSPP_QOS_8LVL, SSPP support 8-level QoS control * @DPU_SSPP_EXCL_RECT, SSPP supports exclusion rect - * @DPU_SSPP_SMART_DMA_V1, SmartDMA 1.0 support - * @DPU_SSPP_SMART_DMA_V2, SmartDMA 2.0 support * @DPU_SSPP_TS_PREFILL Supports prefill with traffic shaper * @DPU_SSPP_TS_PREFILL_REC1 Supports prefill with traffic shaper multirec * @DPU_SSPP_CDP Supports client driven prefetch @@ -124,8 +134,6 @@ enum { DPU_SSPP_QOS, DPU_SSPP_QOS_8LVL, DPU_SSPP_EXCL_RECT, - DPU_SSPP_SMART_DMA_V1, - DPU_SSPP_SMART_DMA_V2, DPU_SSPP_TS_PREFILL, DPU_SSPP_TS_PREFILL_REC1, DPU_SSPP_CDP, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c index 2be43d5a235a..f93cdeb08ac7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c @@ -648,7 +648,8 @@ static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx, } static void _setup_layer_ops(struct dpu_hw_pipe
Re: [Freedreno] [PATCH v2 16/22] drm/msm/dpu: do not limit the zpos property
On 2021-11-09 12:21, Dmitry Baryshkov wrote: On Tue, 9 Nov 2021 at 23:15, wrote: On 2021-07-04 18:21, Dmitry Baryshkov wrote: > Stop limiting zpos property values, we use normalized_zpos anyway. And > nothing stops userspace from assigning several planes to a single zpos > (it is a userspace bug, but the kernel is forgiving about it). Userspace assigning several planes to a single zpos was intended to identify cases where src split can be used. Downstream does not use normalized zpos, hence it did not come across as a bug but mostly as a way to identify when usermode needs src split to be enabled based on the composition strategy. We can talk about that more in the rest of the patches of this series. For this one, I only have a couple of questions: 1) Across different vendors, some have gone with limiting the zpos and some have gone with the max, so is there an issue with sticking with the max_blend_stages limit? 2) If there is no hard reason to make this change, I think its better to keep it the way it is. Short answer to both questions: we want to have more planes than the max_blend_stages. So we should remove the limit. Consider this to be a unification with MDP5, which uses 255 here. Alright, one minor comment below. Also, what you have mentioned now "wanting to have more planes than blend stages" should goto the commit text and the userspace bug part can be omitted as its technically isnt a bug but just the way we intended it to be. > > Signed-off-by: Dmitry Baryshkov > --- > drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 11 +-- > 1 file changed, 1 insertion(+), 10 deletions(-) > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c > b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c > index 8ed7b8f0db69..3850f2714bf3 100644 > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c > @@ -44,7 +44,6 @@ > #define DPU_NAME_SIZE 12 > > #define DPU_PLANE_COLOR_FILL_FLAGBIT(31) > -#define DPU_ZPOS_MAX 255 instead of getting rid of this, you can use this macro below where 255 is hardcoded. > > /* multirect rect index */ > enum { > @@ -1374,7 +1373,6 @@ struct drm_plane *dpu_plane_init(struct > drm_device *dev, > struct dpu_plane *pdpu; > struct msm_drm_private *priv = dev->dev_private; > struct dpu_kms *kms = to_dpu_kms(priv->kms); > - int zpos_max = DPU_ZPOS_MAX; > uint32_t num_formats; > int ret = -EINVAL; > > @@ -1412,14 +1410,7 @@ struct drm_plane *dpu_plane_init(struct > drm_device *dev, > > pdpu->catalog = kms->catalog; > > - if (kms->catalog->mixer_count && > - kms->catalog->mixer[0].sblk->maxblendstages) { > - zpos_max = kms->catalog->mixer[0].sblk->maxblendstages - 1; > - if (zpos_max > DPU_STAGE_MAX - DPU_STAGE_0 - 1) > - zpos_max = DPU_STAGE_MAX - DPU_STAGE_0 - 1; > - } > - > - ret = drm_plane_create_zpos_property(plane, 0, 0, zpos_max); > + ret = drm_plane_create_zpos_property(plane, 0, 0, 255); > if (ret) > DPU_ERROR("failed to install zpos property, rc = %d\n", ret);
Re: [Freedreno] [PATCH v2 17/22] drm/msm/dpu: add support for SSPP allocation to RM
On 2021-07-04 18:21, Dmitry Baryshkov wrote: Add support for handling and allocting SSPP blocks through the resource manager. Handling code is not converted to use it though. Signed-off-by: Dmitry Baryshkov Conceptually this is identical to the previous attempt from QC on this: https://patchwork.kernel.org/project/dri-devel/patch/1529499020-8499-5-git-send-email-skoll...@codeaurora.org/ So I wanted to get your comments on the foll questions: 1) Originally the idea was that to add 4K support to DPU, we will expand on top of your series. From our prior discussion on why the previous QC attempt was not taken over to add multirect support, the reason was that it removed mutirect support which is was actually the end goal of this series. The end goal of the previous attempt was to add 4K support hence looks like multirect was given lower priority and removed that time and not added back. But overall idea is the same which is to allocate hw sspps for drm planes to suit the requirement needed in the dpu_rm. So to add 4K support on top of this series, we would just have to tweak dpu_rm_get_sspp to allocate 2x hw sspps right? 2) If the sspps are going to be iterated over a loop potentially every frame in the atomic check, wouldnt there be a performance hit due to this? +retry_loop: + for (i = 0; i < ARRAY_SIZE(rm->sspp_blks) && pipe == SSPP_NONE; i++) { This is where some help from usermode will help to optimize number of atomic_checks coming in. If usermode tries atomic_checks too many times there can be potential glitches with this. Is that something factored into this design? --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 10 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 18 ++--- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 81 + drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 6 ++ 5 files changed, 104 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h index 00098e33391e..c5ac8defa073 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h @@ -387,6 +387,16 @@ struct dpu_hw_pipe { struct dpu_hw_sspp_ops ops; }; +/** + * to_dpu_hw_pipe - 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_pipe *to_dpu_hw_pipe(struct dpu_hw_blk *hw) +{ + return container_of(hw, struct dpu_hw_pipe, base); +} + /** * dpu_hw_sspp_init - initializes the sspp hw driver object. * Should be called once before accessing every pipe. diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index ab65c817eb42..04a2ab548f54 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -159,6 +159,7 @@ struct dpu_global_state { 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]; + uint32_t pipe_to_plane_id[SSPP_MAX - SSPP_NONE]; }; struct dpu_global_state diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 3850f2714bf3..61008e8afb0a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -1234,8 +1234,6 @@ static void dpu_plane_destroy(struct drm_plane *plane) /* this will destroy the states as well */ drm_plane_cleanup(plane); - dpu_hw_sspp_destroy(pdpu->pipe_hw); - kfree(pdpu); } } @@ -1389,14 +1387,13 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, pdpu->pipe = pipe; /* initialize underlying h/w driver */ - pdpu->pipe_hw = dpu_hw_sspp_init(pipe, kms->mmio, kms->catalog); - if (IS_ERR(pdpu->pipe_hw)) { - DPU_ERROR("[%u]SSPP init failed\n", pipe); - ret = PTR_ERR(pdpu->pipe_hw); + if (!kms->rm.sspp_blks[pipe - SSPP_NONE]) goto clean_plane; - } else if (!pdpu->pipe_hw->cap || !pdpu->pipe_hw->cap->sblk) { + pdpu->pipe_hw = to_dpu_hw_pipe(kms->rm.sspp_blks[pipe - SSPP_NONE]); + + if (!pdpu->pipe_hw->cap || !pdpu->pipe_hw->cap->sblk) { DPU_ERROR("[%u]SSPP init returned invalid cfg\n", pipe); - goto clean_sspp; + goto clean_plane; } format_list = pdpu->pipe_hw->cap->sblk->format_list; @@ -1406,7 +1403,7 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, format_list, num_formats, supported_format_modifiers, type, NULL); if (ret) - goto clean_sspp; + goto clean_plane; pdpu->catalog = kms->catalog; @@ -1432,9 +1429,6 @@
Re: [Freedreno] [PATCH v2 16/22] drm/msm/dpu: do not limit the zpos property
On 2021-07-04 18:21, Dmitry Baryshkov wrote: Stop limiting zpos property values, we use normalized_zpos anyway. And nothing stops userspace from assigning several planes to a single zpos (it is a userspace bug, but the kernel is forgiving about it). Userspace assigning several planes to a single zpos was intended to identify cases where src split can be used. Downstream does not use normalized zpos, hence it did not come across as a bug but mostly as a way to identify when usermode needs src split to be enabled based on the composition strategy. We can talk about that more in the rest of the patches of this series. For this one, I only have a couple of questions: 1) Across different vendors, some have gone with limiting the zpos and some have gone with the max, so is there an issue with sticking with the max_blend_stages limit? 2) If there is no hard reason to make this change, I think its better to keep it the way it is. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 11 +-- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 8ed7b8f0db69..3850f2714bf3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -44,7 +44,6 @@ #define DPU_NAME_SIZE 12 #define DPU_PLANE_COLOR_FILL_FLAG BIT(31) -#define DPU_ZPOS_MAX 255 /* multirect rect index */ enum { @@ -1374,7 +1373,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, struct dpu_plane *pdpu; struct msm_drm_private *priv = dev->dev_private; struct dpu_kms *kms = to_dpu_kms(priv->kms); - int zpos_max = DPU_ZPOS_MAX; uint32_t num_formats; int ret = -EINVAL; @@ -1412,14 +1410,7 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, pdpu->catalog = kms->catalog; - if (kms->catalog->mixer_count && - kms->catalog->mixer[0].sblk->maxblendstages) { - zpos_max = kms->catalog->mixer[0].sblk->maxblendstages - 1; - if (zpos_max > DPU_STAGE_MAX - DPU_STAGE_0 - 1) - zpos_max = DPU_STAGE_MAX - DPU_STAGE_0 - 1; - } - - ret = drm_plane_create_zpos_property(plane, 0, 0, zpos_max); + ret = drm_plane_create_zpos_property(plane, 0, 0, 255); if (ret) DPU_ERROR("failed to install zpos property, rc = %d\n", ret);
Re: [Freedreno] [PATCH v2 15/22] drm/msm/dpu: simplify DPU_SSPP features checks
On 2021-07-04 18:21, Dmitry Baryshkov wrote: Add DPU_SSPP_CSC_ANY denoting any CSC block. As we are at it, rewrite DPU_SSPP_SCALER (any scaler) to use BIT(x) instead of hand-coded bitshifts. This can go independent of the multi-rect series, so can you please take this with the first half of the series which was going to be taken separately? With that, Reviewed-by: Abhinav Kumar Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 16 +++- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 3 +-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h index 264a9d0d5fca..00098e33391e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h @@ -25,11 +25,17 @@ struct dpu_hw_pipe; /** * Define all scaler feature bits in catalog */ -#define DPU_SSPP_SCALER ((1UL << DPU_SSPP_SCALER_RGB) | \ - (1UL << DPU_SSPP_SCALER_QSEED2) | \ -(1UL << DPU_SSPP_SCALER_QSEED3) | \ -(1UL << DPU_SSPP_SCALER_QSEED3LITE) | \ - (1UL << DPU_SSPP_SCALER_QSEED4)) +#define DPU_SSPP_SCALER (BIT(DPU_SSPP_SCALER_RGB) | \ +BIT(DPU_SSPP_SCALER_QSEED2) | \ +BIT(DPU_SSPP_SCALER_QSEED3) | \ +BIT(DPU_SSPP_SCALER_QSEED3LITE) | \ +BIT(DPU_SSPP_SCALER_QSEED4)) + +/* + * Define all CSC feature bits in catalog + */ +#define DPU_SSPP_CSC_ANY (BIT(DPU_SSPP_CSC) | \ + BIT(DPU_SSPP_CSC_10BIT)) /** * Component indices diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 34ecd971cbbb..8ed7b8f0db69 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -983,8 +983,7 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, if (DPU_FORMAT_IS_YUV(fmt) && (!(pdpu->pipe_hw->cap->features & DPU_SSPP_SCALER) || -!(pdpu->pipe_hw->cap->features & (BIT(DPU_SSPP_CSC) -| BIT(DPU_SSPP_CSC_10BIT) { +!(pdpu->pipe_hw->cap->features & DPU_SSPP_CSC_ANY))) { DPU_DEBUG_PLANE(pdpu, "plane doesn't have scaler/csc for yuv\n"); return -EINVAL;
Re: [Freedreno] [PATCH v2 14/22] drm/msm/dpu: add list of supported formats to the DPU caps
On 2021-07-04 18:21, Dmitry Baryshkov wrote: As we are going to add virtual planes, add the list of supported formats to the hw catalog entry. It will be used to setup universal planes, with later selecting a pipe depending on whether the YUV format is used for the framebuffer. Signed-off-by: Dmitry Baryshkov I dont see an issue with exposing the format_list in the catalog, hence Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 10 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 4 2 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index d01c4c919504..b8e0fece1f0b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -195,6 +195,8 @@ static const struct dpu_caps sdm845_dpu_caps = { .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, .max_hdeci_exp = MAX_HORZ_DECIMATION, .max_vdeci_exp = MAX_VERT_DECIMATION, + .format_list = plane_formats_yuv, + .num_formats = ARRAY_SIZE(plane_formats_yuv), }; static const struct dpu_caps sc7180_dpu_caps = { @@ -207,6 +209,8 @@ static const struct dpu_caps sc7180_dpu_caps = { .has_idle_pc = true, .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, + .format_list = plane_formats_yuv, + .num_formats = ARRAY_SIZE(plane_formats_yuv), }; static const struct dpu_caps sm8150_dpu_caps = { @@ -223,6 +227,8 @@ static const struct dpu_caps sm8150_dpu_caps = { .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, .max_hdeci_exp = MAX_HORZ_DECIMATION, .max_vdeci_exp = MAX_VERT_DECIMATION, + .format_list = plane_formats_yuv, + .num_formats = ARRAY_SIZE(plane_formats_yuv), }; static const struct dpu_caps sm8250_dpu_caps = { @@ -237,6 +243,8 @@ static const struct dpu_caps sm8250_dpu_caps = { .has_3d_merge = true, .max_linewidth = 4096, .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, + .format_list = plane_formats_yuv, + .num_formats = ARRAY_SIZE(plane_formats_yuv), }; static const struct dpu_caps sc7280_dpu_caps = { @@ -249,6 +257,8 @@ static const struct dpu_caps sc7280_dpu_caps = { .has_idle_pc = true, .max_linewidth = 2400, .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, + .format_list = plane_formats_yuv, + .num_formats = ARRAY_SIZE(plane_formats_yuv), }; static const struct dpu_mdp_cfg sdm845_mdp[] = { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index d2a945a27cfa..f3c5aa3f4b3f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -324,6 +324,8 @@ struct dpu_qos_lut_tbl { * @pixel_ram_size size of latency hiding and de-tiling buffer in bytes * @max_hdeci_exp max horizontal decimation supported (max is 2^value) * @max_vdeci_exp max vertical decimation supported (max is 2^value) + * @format_list: Pointer to list of supported formats + * @num_formats: Number of supported formats */ struct dpu_caps { u32 max_mixer_width; @@ -340,6 +342,8 @@ struct dpu_caps { u32 pixel_ram_size; u32 max_hdeci_exp; u32 max_vdeci_exp; + const u32 *format_list; + u32 num_formats; }; /**
Re: [Freedreno] [PATCH v3 04/14] drm/hdcp: Expand HDCP helper library for enable/disable/check
On 2021-10-01 08:11, Sean Paul wrote: From: Sean Paul This patch expands upon the HDCP helper library to manage HDCP enable, disable, and check. Previous to this patch, the majority of the state management and sink interaction is tucked inside the Intel driver with the understanding that once a new platform supported HDCP we could make good decisions about what should be centralized. With the addition of HDCP support for Qualcomm, it's time to migrate the protocol-specific bits of HDCP authentication, key exchange, and link checks to the HDCP helper. In terms of functionality, this migration is 1:1 with the Intel driver, however things are laid out a bit differently than with intel_hdcp.c, which is why this is a separate patch from the i915 transition to the helper. On i915, the "shim" vtable is used to account for HDMI vs. DP vs. DP-MST differences whereas the helper library uses a LUT to account for the register offsets and a remote read function to route the messages. On i915, storing the sink information in the source is done inline whereas now we use the new drm_hdcp_helper_funcs vtable to store and fetch information to/from source hw. Finally, instead of calling enable/disable directly from the driver, we'll leave that decision to the helper and by calling drm_hdcp_helper_atomic_commit() from the driver. All told, this will centralize the protocol and state handling in the helper, ensuring we collect all of our bugs^Wlogic in one place. Cc: Abhinav Kumar Acked-by: Jani Nikula Signed-off-by: Sean Paul For vendors/chipsets supporting HW polling, this needs rework to skip the SW polling, as agreed this will be done in a follow up change. Hence, Reviewed-by: Abhinav Kumar Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-5-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-5-s...@poorly.run #v2 Changes in v2: -Fixed set-but-unused variable identified by 0-day Changes in v3: -Fixed uninitialized variable warning identified by 0-day --- drivers/gpu/drm/drm_hdcp.c | 1103 include/drm/drm_hdcp.h | 191 +++ 2 files changed, 1294 insertions(+) diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c index 8c851d40cd45..2bfa07fc3fbc 100644 --- a/drivers/gpu/drm/drm_hdcp.c +++ b/drivers/gpu/drm/drm_hdcp.c @@ -6,15 +6,20 @@ * Ramalingam C */ +#include #include #include #include +#include +#include #include #include #include +#include #include #include +#include #include #include #include @@ -513,3 +518,1101 @@ bool drm_hdcp_atomic_check(struct drm_connector *connector, return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_atomic_check); + +struct drm_hdcp_helper_data { + struct mutex mutex; + struct mutex *driver_mutex; + + struct drm_connector *connector; + const struct drm_hdcp_helper_funcs *funcs; + + u64 value; + unsigned int enabled_type; + + struct delayed_work check_work; + struct work_struct prop_work; + + struct drm_dp_aux *aux; + const struct drm_hdcp_hdcp1_receiver_reg_lut *hdcp1_lut; +}; + +struct drm_hdcp_hdcp1_receiver_reg_lut { + unsigned int bksv; + unsigned int ri; + unsigned int aksv; + unsigned int an; + unsigned int ainfo; + unsigned int v[5]; + unsigned int bcaps; + unsigned int bcaps_mask_repeater_present; + unsigned int bstatus; +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_ddc_lut = { + .bksv = DRM_HDCP_DDC_BKSV, + .ri = DRM_HDCP_DDC_RI_PRIME, + .aksv = DRM_HDCP_DDC_AKSV, + .an = DRM_HDCP_DDC_AN, + .ainfo = DRM_HDCP_DDC_AINFO, + .v = { DRM_HDCP_DDC_V_PRIME(0), DRM_HDCP_DDC_V_PRIME(1), + DRM_HDCP_DDC_V_PRIME(2), DRM_HDCP_DDC_V_PRIME(3), + DRM_HDCP_DDC_V_PRIME(4) }, + .bcaps = DRM_HDCP_DDC_BCAPS, + .bcaps_mask_repeater_present = DRM_HDCP_DDC_BCAPS_REPEATER_PRESENT, + .bstatus = DRM_HDCP_DDC_BSTATUS, +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_dpcd_lut = { + .bksv = DP_AUX_HDCP_BKSV, + .ri = DP_AUX_HDCP_RI_PRIME, + .aksv = DP_AUX_HDCP_AKSV, + .an = DP_AUX_HDCP_AN, + .ainfo = DP_AUX_HDCP_AINFO, + .v = { DP_AUX_HDCP_V_PRIME(0), DP_AUX_HDCP_V_PRIME(1), + DP_AUX_HDCP_V_PRIME(2), DP_AUX_HDCP_V_PRIME(3), + DP_AUX_HDCP_V_PRIME(4) }, + .bcaps = DP_AUX_HDCP_BCAPS, + .bcaps_mask_repeater_present = DP_BCAPS_REPEATER_PRESENT, + + /* +* For some reason the HDMI and DP HDCP specs call this register + * definition by different names. In the HDMI spec, it's called BSTATUS, +* but in DP it's called BINFO. +*/ + .bstatus = DP_AUX_HDCP_BINFO, +}; + +static int drm_hdcp_remote_ddc_read(struct i2c_adapter *i2c, + unsigned int offset,
Re: [Freedreno] [PATCH v3 09/14] drm/msm/dpu: Remove useless checks in dpu_encoder
On 2021-10-01 08:11, Sean Paul wrote: From: Sean Paul A couple more useless checks to remove in dpu_encoder. Reviewed-by: Stephen Boyd Signed-off-by: Sean Paul Reviewed-by: Abhinav Kumar Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-10-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-10-s...@poorly.run #v2 Changes in v2: -None Changes in v3: -None --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 12 1 file changed, 12 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 0e9d3fa1544b..984f8a59cb73 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1153,10 +1153,6 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) struct msm_drm_private *priv; struct drm_display_mode *cur_mode = NULL; - if (!drm_enc) { - DPU_ERROR("invalid encoder\n"); - return; - } dpu_enc = to_dpu_encoder_virt(drm_enc); mutex_lock(_enc->enc_lock); @@ -1203,14 +1199,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) struct msm_drm_private *priv; int i = 0; - if (!drm_enc) { - DPU_ERROR("invalid encoder\n"); - return; - } else if (!drm_enc->dev) { - DPU_ERROR("invalid dev\n"); - return; - } - dpu_enc = to_dpu_encoder_virt(drm_enc); DPU_DEBUG_ENC(dpu_enc, "\n");
Re: [Freedreno] [PATCH v3 03/14] drm/hdcp: Update property value on content type and user changes
On 2021-10-01 08:11, Sean Paul wrote: From: Sean Paul This patch updates the connector's property value in 2 cases which were previously missed: 1- Content type changes. The value should revert back to DESIRED from ENABLED in case the driver must re-authenticate the link due to the new content type. 2- Userspace sets value to DESIRED while ENABLED. In this case, the value should be reset immediately to ENABLED since the link is actively being encrypted. To accommodate these changes, I've split up the conditionals to make things a bit more clear (as much as one can with this mess of state). Acked-by: Jani Nikula Signed-off-by: Sean Paul Reviewed-by: Abhinav Kumar Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-4-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-4-s...@poorly.run #v2 Changes in v2: -None Changes in v3: -Fixed indentation issue identified by 0-day --- drivers/gpu/drm/drm_hdcp.c | 26 +- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c index dd8fa91c51d6..8c851d40cd45 100644 --- a/drivers/gpu/drm/drm_hdcp.c +++ b/drivers/gpu/drm/drm_hdcp.c @@ -487,21 +487,29 @@ bool drm_hdcp_atomic_check(struct drm_connector *connector, return true; /* -* Nothing to do if content type is unchanged and one of: -* - state didn't change +* Content type changes require an HDCP disable/enable cycle. +*/ + if (new_conn_state->hdcp_content_type != old_conn_state->hdcp_content_type) { + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return true; + } + + /* +* Ignore meaningless state changes: * - HDCP was activated since the last commit -* - attempting to set to desired while already enabled +* - Attempting to set to desired while already enabled */ - if (old_hdcp == new_hdcp || - (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && + if ((old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { - if (old_conn_state->hdcp_content_type == - new_conn_state->hdcp_content_type) - return false; + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_ENABLED; + return false; } - return true; + /* Finally, if state changes, we need action */ + return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_atomic_check);
Re: [Freedreno] [PATCH v3 01/14] drm/hdcp: Add drm_hdcp_atomic_check()
On 2021-10-01 08:11, Sean Paul wrote: From: Sean Paul This patch moves the hdcp atomic check from i915 to drm_hdcp so other drivers can use it. No functional changes, just cleaned up some of the code when moving it over. Acked-by: Jani Nikula Signed-off-by: Sean Paul For the drm/hdcp pieces: Reviewed-by: Abhinav Kumar Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-2-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-2-s...@poorly.run #v2 Changes in v2: -None Changes in v3: -None --- drivers/gpu/drm/drm_hdcp.c | 71 - drivers/gpu/drm/i915/display/intel_atomic.c | 4 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 47 -- drivers/gpu/drm/i915/display/intel_hdcp.h | 3 - include/drm/drm_hdcp.h | 3 + 5 files changed, 75 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c index ca9b8f697202..522326b03e66 100644 --- a/drivers/gpu/drm/drm_hdcp.c +++ b/drivers/gpu/drm/drm_hdcp.c @@ -13,13 +13,14 @@ #include #include +#include +#include #include #include #include #include #include #include -#include #include "drm_internal.h" @@ -421,3 +422,71 @@ void drm_hdcp_update_content_protection(struct drm_connector *connector, dev->mode_config.content_protection_property); } EXPORT_SYMBOL(drm_hdcp_update_content_protection); + +/** + * drm_hdcp_atomic_check - Helper for drivers to call during connector->atomic_check + * + * @state: pointer to the atomic state being checked + * @connector: drm_connector on which content protection state needs an update + * + * This function can be used by display drivers to perform an atomic check on the + * hdcp state elements. If hdcp state has changed, this function will set + * mode_changed on the crtc driving the connector so it can update its hardware + * to match the hdcp state. + */ +void drm_hdcp_atomic_check(struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_connector_state *new_conn_state, *old_conn_state; + struct drm_crtc_state *new_crtc_state; + u64 old_hdcp, new_hdcp; + + old_conn_state = drm_atomic_get_old_connector_state(state, connector); + old_hdcp = old_conn_state->content_protection; + + new_conn_state = drm_atomic_get_new_connector_state(state, connector); + new_hdcp = new_conn_state->content_protection; + + if (!new_conn_state->crtc) { + /* +* If the connector is being disabled with CP enabled, mark it +* desired so it's re-enabled when the connector is brought back +*/ + if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return; + } + + new_crtc_state = drm_atomic_get_new_crtc_state(state, + new_conn_state->crtc); + /* + * Fix the HDCP uapi content protection state in case of modeset. + * FIXME: As per HDCP content protection property uapi doc, an uevent() + * need to be sent if there is transition from ENABLED->DESIRED. + */ + if (drm_atomic_crtc_needs_modeset(new_crtc_state) && + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + + /* +* Nothing to do if content type is unchanged and one of: +* - state didn't change +* - HDCP was activated since the last commit +* - attempting to set to desired while already enabled +*/ + if (old_hdcp == new_hdcp || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { + if (old_conn_state->hdcp_content_type == + new_conn_state->hdcp_content_type) + return; + } + + new_crtc_state->mode_changed = true; +} +EXPORT_SYMBOL(drm_hdcp_atomic_check); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index b4e7ac51aa31..1e306e8427ec 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -32,13 +32,13 @@ #include #include #include +#include #include #include "intel_atomic.h" #include "intel_cdclk.h" #include "intel_display_types.h" #include "intel_global_state.h" -#include "intel_hdcp.h" #include "intel_psr.h" #include
Re: [PATCH v3 10/14] drm/msm/dpu: Remove encoder->enable() hack
On 2021-10-01 08:11, Sean Paul wrote: From: Sean Paul encoder->commit() was being misused because there were some global resources which needed to be tweaked in encoder->enable() which were not accessible in dpu_encoder.c. That is no longer true and the redirect serves no purpose any longer. So remove the indirection. Reviewed-by: Stephen Boyd Tested-by: Stephen Boyd Signed-off-by: Sean Paul Reviewed-by: Abhinav Kumar Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-11-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-11-s...@poorly.run #v2 Changes in v2: -None Changes in v3: -None --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 5 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 22 - drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 2 -- drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 4 4 files changed, 1 insertion(+), 32 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 984f8a59cb73..ddc542a0d41f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2122,11 +2122,8 @@ static void dpu_encoder_frame_done_timeout(struct timer_list *t) static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = { .mode_set = dpu_encoder_virt_mode_set, .disable = dpu_encoder_virt_disable, - .enable = dpu_kms_encoder_enable, + .enable = dpu_encoder_virt_enable, .atomic_check = dpu_encoder_virt_atomic_check, - - /* This is called by dpu_kms_encoder_enable */ - .commit = dpu_encoder_virt_enable, }; static const struct drm_encoder_funcs dpu_encoder_funcs = { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index fb0d9f781c66..4a0b55d145ad 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -381,28 +381,6 @@ static void dpu_kms_flush_commit(struct msm_kms *kms, unsigned crtc_mask) } } -/* - * Override the encoder enable since we need to setup the inline rotator and do - * some crtc magic before enabling any bridge that might be present. - */ -void dpu_kms_encoder_enable(struct drm_encoder *encoder) -{ - const struct drm_encoder_helper_funcs *funcs = encoder->helper_private; - struct drm_device *dev = encoder->dev; - struct drm_crtc *crtc; - - /* Forward this enable call to the commit hook */ - if (funcs && funcs->commit) - funcs->commit(encoder); - - drm_for_each_crtc(crtc, dev) { - if (!(crtc->state->encoder_mask & drm_encoder_mask(encoder))) - continue; - - trace_dpu_kms_enc_enable(DRMID(crtc)); - } -} - static void dpu_kms_complete_commit(struct msm_kms *kms, unsigned crtc_mask) { struct dpu_kms *dpu_kms = to_dpu_kms(kms); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 323a6bce9e64..f1ebb60dacab 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -248,8 +248,6 @@ void *dpu_debugfs_get_root(struct dpu_kms *dpu_kms); int dpu_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); void dpu_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); -void dpu_kms_encoder_enable(struct drm_encoder *encoder); - /** * dpu_kms_get_clk_rate() - get the clock rate * @dpu_kms: pointer to dpu_kms structure diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h index 37bba57675a8..54d74341e690 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h @@ -266,10 +266,6 @@ DEFINE_EVENT(dpu_drm_obj_template, dpu_crtc_complete_commit, TP_PROTO(uint32_t drm_id), TP_ARGS(drm_id) ); -DEFINE_EVENT(dpu_drm_obj_template, dpu_kms_enc_enable, - TP_PROTO(uint32_t drm_id), - TP_ARGS(drm_id) -); DEFINE_EVENT(dpu_drm_obj_template, dpu_kms_commit, TP_PROTO(uint32_t drm_id), TP_ARGS(drm_id)
Re: [Freedreno] [PATCH 11/11] drm/msm/dpu: rip out debugfs support from dpu_plane
On 2021-09-30 07:00, Dmitry Baryshkov wrote: In preparations of virtualizing the dpu_plane rip out debugfs support from dpu_plane (as it is mostly used to expose plane's pipe registers). Also move disable_danger file to danger/ debugfs subdir where it belongs. Signed-off-by: Dmitry Baryshkov I am yet to review the second part of the virtual plane series to understand why this removal is necessary so I might be missing something. The plane's debugfs holds useful information to check a few things rightaway. So if there is some misconfiguration or corruption in addition to the plane state, this is good to check. localhost /sys/kernel/debug/dri/1/plane35 # cat src_blk [4000] 03000556 03000556 [4010] 00414000 0040e000 [4020] 1600 0080 [4030] 800236ff 03010002 8001 [4040] 0030 000c0087 0707 [4050] [4060] 0001 [4070] 44556677 00112233 [4080] [4090] [40a0] 00414000 0040e000 [40b0] [40c0] [40d0] 0003f820 [40e0] 0003e2c4 [40f0] 000f000f 00010330 02e402e4 [4100] 03000556 [4110] 03000556 [4120] 03000556 [4130] 000f 000f [4140] So I would like to keep this functionality unless there is some compelling reason to remove this. BTW, are you going to submit the second half as a new series now that most of the first one has been reviewed? --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 123 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 69 - drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 171 +- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 6 + 4 files changed, 69 insertions(+), 300 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index ae48f41821cf..fe33273cdf57 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -101,84 +101,85 @@ static int dpu_debugfs_safe_stats_show(struct seq_file *s, void *v) } DEFINE_SHOW_ATTRIBUTE(dpu_debugfs_safe_stats); -static void dpu_debugfs_danger_init(struct dpu_kms *dpu_kms, - struct dentry *parent) +static ssize_t _dpu_plane_danger_read(struct file *file, + char __user *buff, size_t count, loff_t *ppos) { - struct dentry *entry = debugfs_create_dir("danger", parent); + struct dpu_kms *kms = file->private_data; + int len; + char buf[40]; - debugfs_create_file("danger_status", 0600, entry, - dpu_kms, _debugfs_danger_stats_fops); - debugfs_create_file("safe_status", 0600, entry, - dpu_kms, _debugfs_safe_stats_fops); + len = scnprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl); + + return simple_read_from_buffer(buff, count, ppos, buf, len); } -static int _dpu_debugfs_show_regset32(struct seq_file *s, void *data) +static void _dpu_plane_set_danger_state(struct dpu_kms *kms, bool enable) { - struct dpu_debugfs_regset32 *regset = s->private; - struct dpu_kms *dpu_kms = regset->dpu_kms; - void __iomem *base; - uint32_t i, addr; - - if (!dpu_kms->mmio) - return 0; - - base = dpu_kms->mmio + regset->offset; - - /* insert padding spaces, if needed */ - if (regset->offset & 0xF) { - seq_printf(s, "[%x]", regset->offset & ~0xF); - for (i = 0; i < (regset->offset & 0xF); i += 4) - seq_puts(s, " "); - } - - pm_runtime_get_sync(_kms->pdev->dev); - - /* main register output */ - for (i = 0; i < regset->blk_len; i += 4) { - addr = regset->offset + i; - if ((addr & 0xF) == 0x0) - seq_printf(s, i ? "\n[%x]" : "[%x]", addr); - seq_printf(s, " %08x", readl_relaxed(base + i)); + struct drm_plane *plane; + + drm_for_each_plane(plane, kms->dev) { + if (plane->fb && plane->state) { + dpu_plane_danger_signal_ctrl(plane, enable); + DPU_DEBUG("plane:%d img:%dx%d ", + plane->base.id, plane->fb->width, + plane->fb->height); + DPU_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n", + plane->state->src_x >> 16, + plane->state->src_y >> 16, + plane->state->src_w >> 16, + plane->state->src_h >> 16, +
Re: [Freedreno] [PATCH 10/11] drm/msm/dpu: don't cache pipe->cap->sblk in dpu_plane
On 2021-09-30 07:00, Dmitry Baryshkov wrote: Do not cache hw_pipe's sblk in dpu_plane. Use pdpu->pipe_hw->cap->sblk directly. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 25 --- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index af403c0d3d7d..d8018e664925 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -109,8 +109,6 @@ struct dpu_plane { struct list_head mplane_list; struct dpu_mdss_cfg *catalog; - const struct dpu_sspp_sub_blks *pipe_sblk; - /* debugfs related stuff */ struct dentry *debugfs_root; struct dpu_debugfs_regset32 debugfs_src; @@ -425,9 +423,9 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane, memset(_qos_cfg, 0, sizeof(pipe_qos_cfg)); if (flags & DPU_PLANE_QOS_VBLANK_CTRL) { - pipe_qos_cfg.creq_vblank = pdpu->pipe_sblk->creq_vblank; + pipe_qos_cfg.creq_vblank = pdpu->pipe_hw->cap->sblk->creq_vblank; pipe_qos_cfg.danger_vblank = - pdpu->pipe_sblk->danger_vblank; + pdpu->pipe_hw->cap->sblk->danger_vblank; pipe_qos_cfg.vblank_en = enable; } @@ -982,10 +980,10 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc); - min_scale = FRAC_16_16(1, pdpu->pipe_sblk->maxupscale); + min_scale = FRAC_16_16(1, pdpu->pipe_hw->cap->sblk->maxupscale); ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, min_scale, - pdpu->pipe_sblk->maxdwnscale << 16, + pdpu->pipe_hw->cap->sblk->maxdwnscale << 16, true, true); if (ret) { DPU_DEBUG_PLANE(pdpu, "Check plane state failed (%d)\n", ret); @@ -1611,20 +1609,13 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, goto clean_sspp; } - /* cache features mask for later */ - pdpu->pipe_sblk = pdpu->pipe_hw->cap->sblk; - if (!pdpu->pipe_sblk) { - DPU_ERROR("[%u]invalid sblk\n", pipe); - goto clean_sspp; - } - if (pdpu->is_virtual) { - format_list = pdpu->pipe_sblk->virt_format_list; - num_formats = pdpu->pipe_sblk->virt_num_formats; + format_list = pdpu->pipe_hw->cap->sblk->virt_format_list; + num_formats = pdpu->pipe_hw->cap->sblk->virt_num_formats; } else { - format_list = pdpu->pipe_sblk->format_list; - num_formats = pdpu->pipe_sblk->num_formats; + format_list = pdpu->pipe_hw->cap->sblk->format_list; + num_formats = pdpu->pipe_hw->cap->sblk->num_formats; } ret = drm_universal_plane_init(dev, plane, 0xff, _plane_funcs,
Re: [Freedreno] [PATCH 09/11] drm/msm/dpu: don't cache pipe->cap->features in dpu_plane
On 2021-09-30 07:00, Dmitry Baryshkov wrote: Do not cache hw_pipe's features in dpu_plane. Use pdpu->pipe_hw->cap->features directly. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 12 +--- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index d3ae0cb2047c..af403c0d3d7d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -100,7 +100,6 @@ struct dpu_plane { struct mutex lock; enum dpu_sspp pipe; - uint32_t features; /* capabilities from catalog */ struct dpu_hw_pipe *pipe_hw; uint32_t color_fill; @@ -644,7 +643,7 @@ static const struct dpu_csc_cfg *_dpu_plane_get_csc(struct dpu_plane *pdpu, cons if (!DPU_FORMAT_IS_YUV(fmt)) return NULL; - if (BIT(DPU_SSPP_CSC_10BIT) & pdpu->features) + if (BIT(DPU_SSPP_CSC_10BIT) & pdpu->pipe_hw->cap->features) csc_ptr = _csc10_YUV2RGB_601L; else csc_ptr = _csc_YUV2RGB_601L; @@ -1012,8 +1011,8 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, min_src_size = DPU_FORMAT_IS_YUV(fmt) ? 2 : 1; if (DPU_FORMAT_IS_YUV(fmt) && - (!(pdpu->features & DPU_SSPP_SCALER) || -!(pdpu->features & (BIT(DPU_SSPP_CSC) + (!(pdpu->pipe_hw->cap->features & DPU_SSPP_SCALER) || +!(pdpu->pipe_hw->cap->features & (BIT(DPU_SSPP_CSC) | BIT(DPU_SSPP_CSC_10BIT) { DPU_DEBUG_PLANE(pdpu, "plane doesn't have scaler/csc for yuv\n"); @@ -1439,8 +1438,8 @@ static int _dpu_plane_init_debugfs(struct drm_plane *plane) plane->dev->primary->debugfs_root); /* don't error check these */ - debugfs_create_x32("features", 0600, - pdpu->debugfs_root, >features); + debugfs_create_xul("features", 0600, + pdpu->debugfs_root, (unsigned long *)>pipe_hw->cap->features); /* add register dump support */ dpu_debugfs_setup_regset32(>debugfs_src, @@ -1613,7 +1612,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, } /* cache features mask for later */ - pdpu->features = pdpu->pipe_hw->cap->features; pdpu->pipe_sblk = pdpu->pipe_hw->cap->sblk; if (!pdpu->pipe_sblk) { DPU_ERROR("[%u]invalid sblk\n", pipe);
Re: [Freedreno] [PATCH 08/11] drm/msm/dpu: remove dpu_hw_pipe_cdp_cfg from dpu_plane
On 2021-09-30 06:59, Dmitry Baryshkov wrote: Remove struct dpu_hw_pipe_cdp_cfg instance from dpu_plane, it is an interim configuration structure. Allocate it on stack instead. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 14 +++--- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 2 -- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index b8836c089863..d3ae0cb2047c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -1182,20 +1182,20 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) pstate->multirect_index); if (pdpu->pipe_hw->ops.setup_cdp) { - struct dpu_hw_pipe_cdp_cfg *cdp_cfg = >cdp_cfg; + struct dpu_hw_pipe_cdp_cfg cdp_cfg; - memset(cdp_cfg, 0, sizeof(struct dpu_hw_pipe_cdp_cfg)); + memset(_cfg, 0, sizeof(struct dpu_hw_pipe_cdp_cfg)); - cdp_cfg->enable = pdpu->catalog->perf.cdp_cfg + cdp_cfg.enable = pdpu->catalog->perf.cdp_cfg [DPU_PERF_CDP_USAGE_RT].rd_enable; - cdp_cfg->ubwc_meta_enable = + cdp_cfg.ubwc_meta_enable = DPU_FORMAT_IS_UBWC(fmt); - cdp_cfg->tile_amortize_enable = + cdp_cfg.tile_amortize_enable = DPU_FORMAT_IS_UBWC(fmt) || DPU_FORMAT_IS_TILE(fmt); - cdp_cfg->preload_ahead = DPU_SSPP_CDP_PRELOAD_AHEAD_64; + cdp_cfg.preload_ahead = DPU_SSPP_CDP_PRELOAD_AHEAD_64; - pdpu->pipe_hw->ops.setup_cdp(pdpu->pipe_hw, cdp_cfg); + pdpu->pipe_hw->ops.setup_cdp(pdpu->pipe_hw, _cfg); } } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h index 087194be3c22..1ee5ca5fcdf7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h @@ -23,7 +23,6 @@ * @multirect_index: index of the rectangle of SSPP * @multirect_mode: parallel or time multiplex multirect mode * @pending: whether the current update is still pending - * @cdp_cfg: CDP configuration * @plane_fetch_bw: calculated BW per plane * @plane_clk: calculated clk per plane */ @@ -36,7 +35,6 @@ struct dpu_plane_state { uint32_t multirect_mode; bool pending; - struct dpu_hw_pipe_cdp_cfg cdp_cfg; u64 plane_fetch_bw; u64 plane_clk; };
Re: [Freedreno] [PATCH 07/11] drm/msm/dpu: drop dpu_csc_cfg from dpu_plane
On 2021-09-30 06:59, Dmitry Baryshkov wrote: Simplify code surrounding CSC table setup by removing struct dpu_csc_cfg pointer from dpu_plane and getting it directly at the CSC setup time. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 96 +++-- 5 files changed, 54 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c index cbafb61404d0..103d4bd7585b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c @@ -537,7 +537,7 @@ static void dpu_hw_sspp_setup_sourceaddress(struct dpu_hw_pipe *ctx, } static void dpu_hw_sspp_setup_csc(struct dpu_hw_pipe *ctx, - struct dpu_csc_cfg *data) + const struct dpu_csc_cfg *data) { u32 idx; bool csc10 = false; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h index 27263bc1a1ef..e8939d7387cb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h @@ -262,7 +262,7 @@ struct dpu_hw_sspp_ops { * @ctx: Pointer to pipe context * @data: Pointer to config structure */ - void (*setup_csc)(struct dpu_hw_pipe *ctx, struct dpu_csc_cfg *data); + void (*setup_csc)(struct dpu_hw_pipe *ctx, const struct dpu_csc_cfg *data); /** * setup_solidfill - enable/disable colorfill 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 f94584c982cd..aad85116b0a0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c @@ -374,7 +374,7 @@ u32 dpu_hw_get_scaler3_ver(struct dpu_hw_blk_reg_map *c, void dpu_hw_csc_setup(struct dpu_hw_blk_reg_map *c, u32 csc_reg_off, - struct dpu_csc_cfg *data, bool csc10) + const struct dpu_csc_cfg *data, bool csc10) { static const u32 matrix_shift = 7; u32 clamp_shift = csc10 ? 16 : 8; 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 ff3cffde84cd..bc2fdb2b8f5f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h @@ -321,6 +321,6 @@ u32 dpu_hw_get_scaler3_ver(struct dpu_hw_blk_reg_map *c, void dpu_hw_csc_setup(struct dpu_hw_blk_reg_map *c, u32 csc_reg_off, - struct dpu_csc_cfg *data, bool csc10); + const struct dpu_csc_cfg *data, bool csc10); #endif /* _DPU_HW_UTIL_H */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 4259c4ecde9b..b8836c089863 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -90,7 +90,6 @@ enum dpu_plane_qos { /* * struct dpu_plane - local dpu plane structure * @aspace: address space pointer - * @csc_ptr: Points to dpu_csc_cfg structure to use for current * @mplane_list: List of multirect planes of the same pipe * @catalog: Points to dpu catalog structure * @revalidate: force revalidation of all the plane properties @@ -111,8 +110,6 @@ struct dpu_plane { struct list_head mplane_list; struct dpu_mdss_cfg *catalog; - struct dpu_csc_cfg *csc_ptr; - const struct dpu_sspp_sub_blks *pipe_sblk; /* debugfs related stuff */ @@ -605,51 +602,59 @@ static void _dpu_plane_setup_scaler3(struct dpu_plane *pdpu, scale_cfg->enable = 1; } -static void _dpu_plane_setup_csc(struct dpu_plane *pdpu) -{ - static const struct dpu_csc_cfg dpu_csc_YUV2RGB_601L = { - { - /* S15.16 format */ - 0x00012A00, 0x, 0x00019880, - 0x00012A00, 0x9B80, 0x3000, - 0x00012A00, 0x00020480, 0x, +static const struct dpu_csc_cfg dpu_csc_YUV2RGB_601L = { + { + /* S15.16 format */ + 0x00012A00, 0x, 0x00019880, + 0x00012A00, 0x9B80, 0x3000, + 0x00012A00, 0x00020480, 0x, + }, + /* signed bias */ + { 0xfff0, 0xff80, 0xff80,}, + { 0x0, 0x0, 0x0,}, + /* unsigned clamp */ + { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,}, + { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,}, +}; + +static const struct dpu_csc_cfg dpu_csc10_YUV2RGB_601L = { + { + /* S15.16 format */ + 0x00012A00, 0x, 0x00019880, + 0x00012A00, 0x9B80, 0x3000, + 0x00012A00, 0x00020480, 0x,
Re: [Freedreno] [PATCH 06/11] drm/msm/dpu: drop scaler config from plane state
On 2021-09-30 06:59, Dmitry Baryshkov wrote: Scaler and pixel_ext configuration does not contain a long living state, it is used only during plane update, so remove these two fiels from fiels ---> fields dpu_plane_state and allocate them on stack. Signed-off-by: Dmitry Baryshkov While addressing the bugs reported by the smatch tool, I saw that pe is not being used at the moment. 412 static void _dpu_hw_sspp_setup_scaler3(struct dpu_hw_pipe *ctx, 413 struct dpu_hw_pipe_cfg *sspp, 414 struct dpu_hw_pixel_ext *pe, 415 void *scaler_cfg) 416 { 417 u32 idx; 418 struct dpu_hw_scaler3_cfg *scaler3_cfg = scaler_cfg; 419 420 (void)pe; 421 if (_sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, ) || !sspp 422 || !scaler3_cfg || !ctx || !ctx->cap || !ctx->cap->sblk) 423 return; 424 425 dpu_hw_setup_scaler3(>hw, scaler3_cfg, idx, 426 ctx->cap->sblk->scaler_blk.version, 427 sspp->layout.format); 428 } As part of this change, can you please drop this? --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 59 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 6 --- 2 files changed, 26 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 5288b5b824f8..4259c4ecde9b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -542,14 +542,12 @@ static void _dpu_plane_setup_scaler3(struct dpu_plane *pdpu, struct dpu_plane_state *pstate, uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h, struct dpu_hw_scaler3_cfg *scale_cfg, + struct dpu_hw_pixel_ext *pixel_ext, const struct dpu_format *fmt, uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v) { uint32_t i; - memset(scale_cfg, 0, sizeof(*scale_cfg)); - memset(>pixel_ext, 0, sizeof(struct dpu_hw_pixel_ext)); - scale_cfg->phase_step_x[DPU_SSPP_COMP_0] = mult_frac((1 << PHASE_STEP_SHIFT), src_w, dst_w); scale_cfg->phase_step_y[DPU_SSPP_COMP_0] = @@ -588,9 +586,9 @@ static void _dpu_plane_setup_scaler3(struct dpu_plane *pdpu, scale_cfg->preload_y[i] = DPU_QSEED3_DEFAULT_PRELOAD_V; } - pstate->pixel_ext.num_ext_pxls_top[i] = + pixel_ext->num_ext_pxls_top[i] = scale_cfg->src_height[i]; - pstate->pixel_ext.num_ext_pxls_left[i] = + pixel_ext->num_ext_pxls_left[i] = scale_cfg->src_width[i]; } if (!(DPU_FORMAT_IS_YUV(fmt)) && (src_h == dst_h) @@ -660,6 +658,11 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu, struct dpu_hw_pipe_cfg *pipe_cfg) { const struct drm_format_info *info = drm_format_info(fmt->base.pixel_format); + struct dpu_hw_scaler3_cfg scaler3_cfg; + struct dpu_hw_pixel_ext pixel_ext; + + memset(_cfg, 0, sizeof(scaler3_cfg)); + memset(_ext, 0, sizeof(pixel_ext)); /* don't chroma subsample if decimating */ /* update scaler. calculate default config for QSEED3 */ @@ -668,8 +671,23 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu, drm_rect_height(_cfg->src_rect), drm_rect_width(_cfg->dst_rect), drm_rect_height(_cfg->dst_rect), - >scaler3_cfg, fmt, + _cfg, _ext, fmt, info->hsub, info->vsub); + + if (pdpu->pipe_hw->ops.setup_pe) + pdpu->pipe_hw->ops.setup_pe(pdpu->pipe_hw, + _ext); + + /** +* when programmed in multirect mode, scalar block will be +* bypassed. Still we need to update alpha and bitwidth +* ONLY for RECT0 +*/ + if (pdpu->pipe_hw->ops.setup_scaler && + pstate->multirect_index != DPU_SSPP_RECT_1) + pdpu->pipe_hw->ops.setup_scaler(pdpu->pipe_hw, + pipe_cfg, _ext, + _cfg); } /** @@ -710,7 +728,6 @@ static int _dpu_plane_color_fill(struct dpu_plane *pdpu, drm_rect_width(_cfg.dst_rect); pipe_cfg.src_rect.y2 = drm_rect_height(_cfg.dst_rect); - _dpu_plane_setup_scaler(pdpu, pstate, fmt, true, _cfg); if (pdpu->pipe_hw->ops.setup_format) pdpu->pipe_hw->ops.setup_format(pdpu->pipe_hw, @@ -722,15 +739,7 @@ static int _dpu_plane_color_fill(struct dpu_plane *pdpu, _cfg, pstate->multirect_index); - if (pdpu->pipe_hw->ops.setup_pe) -
Re: [Freedreno] [PATCH 05/11] drm/msm/dpu: move dpu_hw_pipe_cfg out of struct dpu_plane
On 2021-09-30 06:59, Dmitry Baryshkov wrote: struct dpu_hw_pipe_cfg represents an interim state during atomic update/color fill, so move it out of struct dpu_plane. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 104 -- 1 file changed, 57 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index ef3737642b0c..5288b5b824f8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -104,7 +104,6 @@ struct dpu_plane { uint32_t features; /* capabilities from catalog */ struct dpu_hw_pipe *pipe_hw; - struct dpu_hw_pipe_cfg pipe_cfg; uint32_t color_fill; bool is_error; bool is_rt_pipe; @@ -143,14 +142,15 @@ static struct dpu_kms *_dpu_plane_get_kms(struct drm_plane *plane) * _dpu_plane_calc_bw - calculate bandwidth required for a plane * @plane: Pointer to drm plane. * @fb: Pointer to framebuffer associated with the given plane + * @pipe_cfg: Pointer to pipe configuration * Result: Updates calculated bandwidth in the plane state. * BW Equation: src_w * src_h * bpp * fps * (v_total / v_dest) * Prefill BW Equation: line src bytes * line_time */ static void _dpu_plane_calc_bw(struct drm_plane *plane, - struct drm_framebuffer *fb) + struct drm_framebuffer *fb, + struct dpu_hw_pipe_cfg *pipe_cfg) { - struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane_state *pstate; struct drm_display_mode *mode; const struct dpu_format *fmt = NULL; @@ -167,9 +167,9 @@ static void _dpu_plane_calc_bw(struct drm_plane *plane, fmt = dpu_get_dpu_format_ext(fb->format->format, fb->modifier); - src_width = drm_rect_width(>pipe_cfg.src_rect); - src_height = drm_rect_height(>pipe_cfg.src_rect); - dst_height = drm_rect_height(>pipe_cfg.dst_rect); + src_width = drm_rect_width(_cfg->src_rect); + src_height = drm_rect_height(_cfg->src_rect); + dst_height = drm_rect_height(_cfg->dst_rect); fps = drm_mode_vrefresh(mode); vbp = mode->vtotal - mode->vsync_end; vpw = mode->vsync_end - mode->vsync_start; @@ -200,12 +200,12 @@ static void _dpu_plane_calc_bw(struct drm_plane *plane, /** * _dpu_plane_calc_clk - calculate clock required for a plane * @plane: Pointer to drm plane. + * @pipe_cfg: Pointer to pipe configuration * Result: Updates calculated clock in the plane state. * Clock equation: dst_w * v_total * fps * (src_h / dst_h) */ -static void _dpu_plane_calc_clk(struct drm_plane *plane) +static void _dpu_plane_calc_clk(struct drm_plane *plane, struct dpu_hw_pipe_cfg *pipe_cfg) { - struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane_state *pstate; struct drm_display_mode *mode; int dst_width, src_height, dst_height, fps; @@ -213,9 +213,9 @@ static void _dpu_plane_calc_clk(struct drm_plane *plane) pstate = to_dpu_plane_state(plane->state); mode = >state->crtc->mode; - src_height = drm_rect_height(>pipe_cfg.src_rect); - dst_width = drm_rect_width(>pipe_cfg.dst_rect); - dst_height = drm_rect_height(>pipe_cfg.dst_rect); + src_height = drm_rect_height(_cfg->src_rect); + dst_width = drm_rect_width(_cfg->dst_rect); + dst_height = drm_rect_height(_cfg->dst_rect); fps = drm_mode_vrefresh(mode); pstate->plane_clk = @@ -252,14 +252,17 @@ static int _dpu_plane_calc_fill_level(struct drm_plane *plane, fixed_buff_size = pdpu->catalog->caps->pixel_ram_size; list_for_each_entry(tmp, >mplane_list, mplane_list) { + u32 tmp_width; + if (!tmp->base.state->visible) continue; + tmp_width = drm_rect_width(>base.state->src) >> 16; DPU_DEBUG("plane%d/%d src_width:%d/%d\n", pdpu->base.base.id, tmp->base.base.id, src_width, - drm_rect_width(>pipe_cfg.src_rect)); + tmp_width); src_width = max_t(u32, src_width, - drm_rect_width(>pipe_cfg.src_rect)); + tmp_width); } if (fmt->fetch_planes == DPU_PLANE_PSEUDO_PLANAR) { @@ -319,9 +322,10 @@ static u64 _dpu_plane_get_qos_lut(const struct dpu_qos_lut_tbl *tbl, * _dpu_plane_set_qos_lut - set QoS LUT of the given plane * @plane: Pointer to drm plane * @fb:Pointer to framebuffer associated with the given plane + * @pipe_cfg: Pointer to pipe configuration */ static void _dpu_plane_set_qos_lut(struct drm_plane *plane, - struct drm_framebuffer *fb) + struct drm_framebuffer *fb, struct dpu_hw_pipe_cfg
Re: [Freedreno] [PATCH 04/11] drm/msm/dpu: remove stage_cfg from struct dpu_crtc
On 2021-09-30 06:59, Dmitry Baryshkov wrote: The stage_cfg is not used outside of _dpu_crtc_blend_setup(), so remove the temporary config from global struct. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 11 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 2 -- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 768012243b44..19f0715a4089 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -207,7 +207,8 @@ static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc) } static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, - struct dpu_crtc *dpu_crtc, struct dpu_crtc_mixer *mixer) + struct dpu_crtc *dpu_crtc, struct dpu_crtc_mixer *mixer, + struct dpu_hw_stage_cfg *stage_cfg) { struct drm_plane *plane; struct drm_framebuffer *fb; @@ -216,7 +217,6 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct dpu_plane_state *pstate = NULL; struct dpu_format *format; struct dpu_hw_ctl *ctl = mixer->lm_ctl; - struct dpu_hw_stage_cfg *stage_cfg = _crtc->stage_cfg; u32 flush_mask; uint32_t stage_idx, lm_idx; @@ -292,6 +292,7 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc) struct dpu_crtc_mixer *mixer = cstate->mixers; struct dpu_hw_ctl *ctl; struct dpu_hw_mixer *lm; + struct dpu_hw_stage_cfg stage_cfg; int i; DRM_DEBUG_ATOMIC("%s\n", dpu_crtc->name); @@ -305,9 +306,9 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc) } /* initialize stage cfg */ - memset(_crtc->stage_cfg, 0, sizeof(struct dpu_hw_stage_cfg)); + memset(_cfg, 0, sizeof(struct dpu_hw_stage_cfg)); - _dpu_crtc_blend_setup_mixer(crtc, dpu_crtc, mixer); + _dpu_crtc_blend_setup_mixer(crtc, dpu_crtc, mixer, _cfg); for (i = 0; i < cstate->num_mixers; i++) { ctl = mixer[i].lm_ctl; @@ -328,7 +329,7 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc) mixer[i].flush_mask); ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx, - _crtc->stage_cfg); + _cfg); } } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h index cec3474340e8..30535acec670 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -116,7 +116,6 @@ struct dpu_crtc_frame_event { * @drm_requested_vblank : Whether vblanks have been enabled in the encoder * @property_info : Opaque structure for generic property support * @property_defaults : Array of default values for generic property support - * @stage_cfg : H/w mixer stage configuration * @debugfs_root : Parent of debugfs node * @vblank_cb_count : count of vblank callback since last reset * @play_count: frame count between crtc enable and disable @@ -147,7 +146,6 @@ struct dpu_crtc { struct drm_pending_vblank_event *event; u32 vsync_count; - struct dpu_hw_stage_cfg stage_cfg; struct dentry *debugfs_root; u32 vblank_cb_count;
Re: [Freedreno] [PATCH 03/11] drm/msm/dpu: drop pipe_name from struct dpu_plane
On 2021-09-30 06:59, Dmitry Baryshkov wrote: Use plane->name instead of artificial pipe_name. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 8 ++-- 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 88d726133b8b..ef3737642b0c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -115,7 +115,6 @@ struct dpu_plane { struct dpu_csc_cfg *csc_ptr; const struct dpu_sspp_sub_blks *pipe_sblk; - char pipe_name[DPU_NAME_SIZE]; /* debugfs related stuff */ struct dentry *debugfs_root; @@ -1429,7 +1428,7 @@ static int _dpu_plane_init_debugfs(struct drm_plane *plane) /* create overall sub-directory for the pipe */ pdpu->debugfs_root = - debugfs_create_dir(pdpu->pipe_name, + debugfs_create_dir(plane->name, plane->dev->primary->debugfs_root); /* don't error check these */ @@ -1660,12 +1659,9 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, /* success! finalize initialization */ drm_plane_helper_add(plane, _plane_helper_funcs); - /* save user friendly pipe name for later */ - snprintf(pdpu->pipe_name, DPU_NAME_SIZE, "plane%u", plane->base.id); - mutex_init(>lock); - DPU_DEBUG("%s created for pipe:%u id:%u virtual:%u\n", pdpu->pipe_name, + DPU_DEBUG("%s created for pipe:%u id:%u virtual:%u\n", plane->name, pipe, plane->base.id, master_plane_id); return plane;
Re: [Freedreno] [PATCH 02/11] drm/msm/dpu: remove pipe_qos_cfg from struct dpu_plane
On 2021-09-30 06:59, Dmitry Baryshkov wrote: The pipe_qos_cfg is used only in _dpu_plane_set_qos_ctrl(), so remove it from the dpu_plane struct and allocate it on stack when necessary. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 30 --- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 5e0d06f26e53..88d726133b8b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -105,7 +105,6 @@ struct dpu_plane { struct dpu_hw_pipe *pipe_hw; struct dpu_hw_pipe_cfg pipe_cfg; - struct dpu_hw_pipe_qos_cfg pipe_qos_cfg; uint32_t color_fill; bool is_error; bool is_rt_pipe; @@ -422,38 +421,41 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane, bool enable, u32 flags) { struct dpu_plane *pdpu = to_dpu_plane(plane); + struct dpu_hw_pipe_qos_cfg pipe_qos_cfg; + + memset(_qos_cfg, 0, sizeof(pipe_qos_cfg)); if (flags & DPU_PLANE_QOS_VBLANK_CTRL) { - pdpu->pipe_qos_cfg.creq_vblank = pdpu->pipe_sblk->creq_vblank; - pdpu->pipe_qos_cfg.danger_vblank = + pipe_qos_cfg.creq_vblank = pdpu->pipe_sblk->creq_vblank; + pipe_qos_cfg.danger_vblank = pdpu->pipe_sblk->danger_vblank; - pdpu->pipe_qos_cfg.vblank_en = enable; + pipe_qos_cfg.vblank_en = enable; } if (flags & DPU_PLANE_QOS_VBLANK_AMORTIZE) { /* this feature overrules previous VBLANK_CTRL */ - pdpu->pipe_qos_cfg.vblank_en = false; - pdpu->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */ + pipe_qos_cfg.vblank_en = false; + pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */ } if (flags & DPU_PLANE_QOS_PANIC_CTRL) - pdpu->pipe_qos_cfg.danger_safe_en = enable; + pipe_qos_cfg.danger_safe_en = enable; if (!pdpu->is_rt_pipe) { - pdpu->pipe_qos_cfg.vblank_en = false; - pdpu->pipe_qos_cfg.danger_safe_en = false; + pipe_qos_cfg.vblank_en = false; + pipe_qos_cfg.danger_safe_en = false; } DPU_DEBUG_PLANE(pdpu, "pnum:%d ds:%d vb:%d pri[0x%x, 0x%x] is_rt:%d\n", pdpu->pipe - SSPP_VIG0, - pdpu->pipe_qos_cfg.danger_safe_en, - pdpu->pipe_qos_cfg.vblank_en, - pdpu->pipe_qos_cfg.creq_vblank, - pdpu->pipe_qos_cfg.danger_vblank, + pipe_qos_cfg.danger_safe_en, + pipe_qos_cfg.vblank_en, + pipe_qos_cfg.creq_vblank, + pipe_qos_cfg.danger_vblank, pdpu->is_rt_pipe); pdpu->pipe_hw->ops.setup_qos_ctrl(pdpu->pipe_hw, - >pipe_qos_cfg); + _qos_cfg); } /**
Re: [Freedreno] [PATCH 01/11] drm/msm/dpu: move LUT levels out of QOS config
On 2021-09-30 06:59, Dmitry Baryshkov wrote: LUT levels are setup outside of setup_qos_ctrl, so remove them from the struct dpu_hw_pipe_qos_cfg. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 15 --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 16 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 17 ++--- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c index 69eed7932486..cbafb61404d0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c @@ -569,19 +569,20 @@ static void dpu_hw_sspp_setup_solidfill(struct dpu_hw_pipe *ctx, u32 color, enum } static void dpu_hw_sspp_setup_danger_safe_lut(struct dpu_hw_pipe *ctx, - struct dpu_hw_pipe_qos_cfg *cfg) + u32 danger_lut, + u32 safe_lut) { u32 idx; if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, )) return; - DPU_REG_WRITE(>hw, SSPP_DANGER_LUT + idx, cfg->danger_lut); - DPU_REG_WRITE(>hw, SSPP_SAFE_LUT + idx, cfg->safe_lut); + DPU_REG_WRITE(>hw, SSPP_DANGER_LUT + idx, danger_lut); + DPU_REG_WRITE(>hw, SSPP_SAFE_LUT + idx, safe_lut); } static void dpu_hw_sspp_setup_creq_lut(struct dpu_hw_pipe *ctx, - struct dpu_hw_pipe_qos_cfg *cfg) + u64 creq_lut) { u32 idx; @@ -589,11 +590,11 @@ static void dpu_hw_sspp_setup_creq_lut(struct dpu_hw_pipe *ctx, return; if (ctx->cap && test_bit(DPU_SSPP_QOS_8LVL, >cap->features)) { - DPU_REG_WRITE(>hw, SSPP_CREQ_LUT_0 + idx, cfg->creq_lut); + DPU_REG_WRITE(>hw, SSPP_CREQ_LUT_0 + idx, creq_lut); DPU_REG_WRITE(>hw, SSPP_CREQ_LUT_1 + idx, - cfg->creq_lut >> 32); + creq_lut >> 32); } else { - DPU_REG_WRITE(>hw, SSPP_CREQ_LUT + idx, cfg->creq_lut); + DPU_REG_WRITE(>hw, SSPP_CREQ_LUT + idx, creq_lut); } } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h index fdfd4b46e2c6..27263bc1a1ef 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h @@ -166,18 +166,12 @@ struct dpu_hw_pipe_cfg { /** * struct dpu_hw_pipe_qos_cfg : Source pipe QoS configuration - * @danger_lut: LUT for generate danger level based on fill level - * @safe_lut: LUT for generate safe level based on fill level - * @creq_lut: LUT for generate creq level based on fill level * @creq_vblank: creq value generated to vbif during vertical blanking * @danger_vblank: danger value generated during vertical blanking * @vblank_en: enable creq_vblank and danger_vblank during vblank * @danger_safe_en: enable danger safe generation */ struct dpu_hw_pipe_qos_cfg { - u32 danger_lut; - u32 safe_lut; - u64 creq_lut; u32 creq_vblank; u32 danger_vblank; bool vblank_en; @@ -302,20 +296,22 @@ struct dpu_hw_sspp_ops { /** * setup_danger_safe_lut - setup danger safe LUTs * @ctx: Pointer to pipe context -* @cfg: Pointer to pipe QoS configuration +* @danger_lut: LUT for generate danger level based on fill level +* @safe_lut: LUT for generate safe level based on fill level * */ void (*setup_danger_safe_lut)(struct dpu_hw_pipe *ctx, - struct dpu_hw_pipe_qos_cfg *cfg); + u32 danger_lut, + u32 safe_lut); /** * setup_creq_lut - setup CREQ LUT * @ctx: Pointer to pipe context -* @cfg: Pointer to pipe QoS configuration +* @creq_lut: LUT for generate creq level based on fill level * */ void (*setup_creq_lut)(struct dpu_hw_pipe *ctx, - struct dpu_hw_pipe_qos_cfg *cfg); + u64 creq_lut); /** * setup_qos_ctrl - setup QoS control diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index c989621209aa..5e0d06f26e53 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -348,8 +348,6 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane, qos_lut = _dpu_plane_get_qos_lut( >catalog->perf.qos_lut_tbl[lut_usage], total_fl); - pdpu->pipe_qos_cfg.creq_lut = qos_lut; - trace_dpu_perf_set_qos_luts(pdpu->pipe - SSPP_VIG0, (fmt) ? fmt->base.pixel_format : 0, pdpu->is_rt_pipe, total_fl, qos_lut, lut_usage); @@ -359,7 +357,7 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane,
Re: [Freedreno] [PATCH] drm/msm/dsi: use bulk clk API
On 2021-10-01 18:27, Dmitry Baryshkov wrote: Use clk_bulk_* API instead of hand-coding them. Note, this drops support for legacy clk naming (e.g. "iface_clk" instead of just "iface"), however all in-kernel device trees were converted long long ago. The warning is present there since 2017. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/dsi/dsi_host.c | 59 ++ 1 file changed, 12 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index e269df285136..3b81f40bba2e 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -106,7 +106,8 @@ struct msm_dsi_host { phys_addr_t ctrl_size; struct regulator_bulk_data supplies[DSI_DEV_REGULATOR_MAX]; - struct clk *bus_clks[DSI_BUS_CLK_MAX]; + int num_bus_clks; + struct clk_bulk_data bus_clks[DSI_BUS_CLK_MAX]; struct clk *byte_clk; struct clk *esc_clk; @@ -374,15 +375,14 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host) int i, ret = 0; /* get bus clocks */ - for (i = 0; i < cfg->num_bus_clks; i++) { - msm_host->bus_clks[i] = msm_clk_get(pdev, - cfg->bus_clk_names[i]); - if (IS_ERR(msm_host->bus_clks[i])) { - ret = PTR_ERR(msm_host->bus_clks[i]); - pr_err("%s: Unable to get %s clock, ret = %d\n", - __func__, cfg->bus_clk_names[i], ret); - goto exit; - } + for (i = 0; i < cfg->num_bus_clks; i++) + msm_host->bus_clks[i].id = cfg->bus_clk_names[i]; + msm_host->num_bus_clks = cfg->num_bus_clks; + + ret = devm_clk_bulk_get(>dev, msm_host->num_bus_clks, msm_host->bus_clks); + if (ret < 0) { + dev_err(>dev, "Unable to get clocks, ret = %d\n", ret); + goto exit; } /* get link and source clocks */ @@ -433,41 +433,6 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host) return ret; } -static int dsi_bus_clk_enable(struct msm_dsi_host *msm_host) -{ - const struct msm_dsi_config *cfg = msm_host->cfg_hnd->cfg; - int i, ret; - - DBG("id=%d", msm_host->id); - - for (i = 0; i < cfg->num_bus_clks; i++) { - ret = clk_prepare_enable(msm_host->bus_clks[i]); - if (ret) { - pr_err("%s: failed to enable bus clock %d ret %d\n", - __func__, i, ret); - goto err; - } - } - - return 0; -err: - for (; i > 0; i--) - clk_disable_unprepare(msm_host->bus_clks[i]); - - return ret; -} - -static void dsi_bus_clk_disable(struct msm_dsi_host *msm_host) -{ - const struct msm_dsi_config *cfg = msm_host->cfg_hnd->cfg; - int i; - - DBG(""); - - for (i = cfg->num_bus_clks - 1; i >= 0; i--) - clk_disable_unprepare(msm_host->bus_clks[i]); -} - int msm_dsi_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -478,7 +443,7 @@ int msm_dsi_runtime_suspend(struct device *dev) if (!msm_host->cfg_hnd) return 0; - dsi_bus_clk_disable(msm_host); + clk_bulk_disable_unprepare(msm_host->num_bus_clks, msm_host->bus_clks); return 0; } @@ -493,7 +458,7 @@ int msm_dsi_runtime_resume(struct device *dev) if (!msm_host->cfg_hnd) return 0; - return dsi_bus_clk_enable(msm_host); + return clk_bulk_prepare_enable(msm_host->num_bus_clks, msm_host->bus_clks); } int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host)
Re: [Freedreno] [PATCH 2/2] drm/msm/dsi: stop setting clock parents manually
On 2021-10-06 13:48, Dmitry Baryshkov wrote: There is no reason to set clock parents manually, use device tree to assign DSI/display clock parents to DSI PHY clocks. Dropping this manual setup allows us to drop repeating code and to move registration of hw clock providers to generic place. Signed-off-by: Dmitry Baryshkov I believe this was reviewed previously on https://patchwork.freedesktop.org/patch/443470/ Hence, Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/dsi/dsi.h | 2 - drivers/gpu/drm/msm/dsi/dsi_host.c| 53 --- drivers/gpu/drm/msm/dsi/dsi_manager.c | 11 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 11 -- 4 files changed, 2 insertions(+), 75 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 7dfb6d198ca9..c03a8d09c764 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -173,8 +173,6 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, void msm_dsi_phy_disable(struct msm_dsi_phy *phy); void msm_dsi_phy_set_usecase(struct msm_dsi_phy *phy, enum msm_dsi_phy_usecase uc); -int msm_dsi_phy_get_clk_provider(struct msm_dsi_phy *phy, - struct clk **byte_clk_provider, struct clk **pixel_clk_provider); void msm_dsi_phy_pll_save_state(struct msm_dsi_phy *phy); int msm_dsi_phy_pll_restore_state(struct msm_dsi_phy *phy); void msm_dsi_phy_snapshot(struct msm_disp_state *disp_state, struct msm_dsi_phy *phy); diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 1ffcd0577e99..9600b4fa27eb 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -2232,59 +2232,6 @@ void msm_dsi_host_set_phy_mode(struct mipi_dsi_host *host, msm_host->cphy_mode = src_phy->cphy_mode; } -int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, - struct msm_dsi_phy *src_phy) -{ - struct msm_dsi_host *msm_host = to_msm_dsi_host(host); - struct clk *byte_clk_provider, *pixel_clk_provider; - int ret; - - msm_host->cphy_mode = src_phy->cphy_mode; - - ret = msm_dsi_phy_get_clk_provider(src_phy, - _clk_provider, _clk_provider); - if (ret) { - pr_info("%s: can't get provider from pll, don't set parent\n", - __func__); - return 0; - } - - ret = clk_set_parent(msm_host->byte_clk_src, byte_clk_provider); - if (ret) { - pr_err("%s: can't set parent to byte_clk_src. ret=%d\n", - __func__, ret); - goto exit; - } - - ret = clk_set_parent(msm_host->pixel_clk_src, pixel_clk_provider); - if (ret) { - pr_err("%s: can't set parent to pixel_clk_src. ret=%d\n", - __func__, ret); - goto exit; - } - - if (msm_host->dsi_clk_src) { - ret = clk_set_parent(msm_host->dsi_clk_src, pixel_clk_provider); - if (ret) { - pr_err("%s: can't set parent to dsi_clk_src. ret=%d\n", - __func__, ret); - goto exit; - } - } - - if (msm_host->esc_clk_src) { - ret = clk_set_parent(msm_host->esc_clk_src, byte_clk_provider); - if (ret) { - pr_err("%s: can't set parent to esc_clk_src. ret=%d\n", - __func__, ret); - goto exit; - } - } - -exit: - return ret; -} - void msm_dsi_host_reset_phy(struct mipi_dsi_host *host) { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 49a0a0841487..9342a822ad20 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -78,10 +78,7 @@ static int dsi_mgr_setup_components(int id) msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE); msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); - ret = msm_dsi_host_set_src_pll(msm_dsi->host, msm_dsi->phy); - } else if (!other_dsi) { - ret = 0; - } else { + } else if (other_dsi) { struct msm_dsi *master_link_dsi = IS_MASTER_DSI_LINK(id) ? msm_dsi : other_dsi; struct msm_dsi *slave_link_dsi = IS_MASTER_DSI_LINK(id) ? @@ -107,13 +104,9 @@ static int dsi_mgr_setup_components(int id) MSM_DSI_PHY_SLAVE); msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); msm_dsi_host_set_phy_mode(other_dsi->host, other_dsi->phy); - ret = msm_dsi_host_set_src_pll(msm_dsi->host, clk_master_dsi->phy); - if (ret) -
Re: [Freedreno] [PATCH 1/2] drm/msm/dsi: untangle cphy setting from the src pll setting
On 2021-10-06 13:48, Dmitry Baryshkov wrote: Move DPHY/CPHY setting from msm_dsi_host_set_src_pll() to new function msm_dsi_host_set_phy_mode(). Signed-off-by: Dmitry Baryshkov Just a minor comment, can you also include the part which removes msm_host->cphy_mode = src_phy->cphy_mode; from msm_dsi_host_set_src_pll in this change itself so that its clear that you are removing from there and moving it into a new API? You can still keep my Reviewed-by: Abhinav Kumar once you address this. --- drivers/gpu/drm/msm/dsi/dsi.h | 2 ++ drivers/gpu/drm/msm/dsi/dsi_host.c| 8 drivers/gpu/drm/msm/dsi/dsi_manager.c | 3 +++ 3 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index b50db91cb8a7..7dfb6d198ca9 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -118,6 +118,8 @@ unsigned long msm_dsi_host_get_mode_flags(struct mipi_dsi_host *host); struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host); int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer); void msm_dsi_host_unregister(struct mipi_dsi_host *host); +void msm_dsi_host_set_phy_mode(struct mipi_dsi_host *host, + struct msm_dsi_phy *src_phy); int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, struct msm_dsi_phy *src_phy); void msm_dsi_host_reset_phy(struct mipi_dsi_host *host); diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index e269df285136..1ffcd0577e99 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -2224,6 +2224,14 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, u32 dma_base, wmb(); } +void msm_dsi_host_set_phy_mode(struct mipi_dsi_host *host, + struct msm_dsi_phy *src_phy) +{ + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + + msm_host->cphy_mode = src_phy->cphy_mode; +} + int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, struct msm_dsi_phy *src_phy) { diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index c41d39f5b7cf..49a0a0841487 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -77,6 +77,7 @@ static int dsi_mgr_setup_components(int id) return ret; msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE); + msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); ret = msm_dsi_host_set_src_pll(msm_dsi->host, msm_dsi->phy); } else if (!other_dsi) { ret = 0; @@ -104,6 +105,8 @@ static int dsi_mgr_setup_components(int id) MSM_DSI_PHY_MASTER); msm_dsi_phy_set_usecase(clk_slave_dsi->phy, MSM_DSI_PHY_SLAVE); + msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); + msm_dsi_host_set_phy_mode(other_dsi->host, other_dsi->phy); ret = msm_dsi_host_set_src_pll(msm_dsi->host, clk_master_dsi->phy); if (ret) return ret;
Re: [Freedreno] [PATCH 2/2] drm/msm/hdmi: switch to drm_bridge_connector
On 2021-10-16 07:21, Dmitry Baryshkov wrote: On Sat, 16 Oct 2021 at 01:25, wrote: Hi Dmitry On 2021-10-14 17:11, Dmitry Baryshkov wrote: > Merge old hdmi_bridge and hdmi_connector implementations. Use > drm_bridge_connector instead. > Can you please comment on the validation done on this change? Has basic bootup been verified on db820c as thats the only platform which shall use this. Yes, this has been developed and validated on db820c Thanks for confirming. > Signed-off-by: Dmitry Baryshkov > --- > drivers/gpu/drm/msm/Makefile | 2 +- > drivers/gpu/drm/msm/hdmi/hdmi.c | 12 +- > drivers/gpu/drm/msm/hdmi/hdmi.h | 19 ++- > drivers/gpu/drm/msm/hdmi/hdmi_bridge.c| 81 - > .../msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} | 154 ++ > 5 files changed, 109 insertions(+), 159 deletions(-) > rename drivers/gpu/drm/msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} (62%) > > diff --git a/drivers/gpu/drm/msm/Makefile > b/drivers/gpu/drm/msm/Makefile > index 904535eda0c4..91b09cda8a9c 100644 > --- a/drivers/gpu/drm/msm/Makefile > +++ b/drivers/gpu/drm/msm/Makefile > @@ -19,7 +19,7 @@ msm-y := \ > hdmi/hdmi.o \ > hdmi/hdmi_audio.o \ > hdmi/hdmi_bridge.o \ > - hdmi/hdmi_connector.o \ > + hdmi/hdmi_hpd.o \ > hdmi/hdmi_i2c.o \ > hdmi/hdmi_phy.o \ > hdmi/hdmi_phy_8960.o \ > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c > b/drivers/gpu/drm/msm/hdmi/hdmi.c > index db17a000d968..d1cf4df7188c 100644 > --- a/drivers/gpu/drm/msm/hdmi/hdmi.c > +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c > @@ -8,6 +8,8 @@ > #include > #include > > +#include > + > #include > #include "hdmi.h" > > @@ -41,7 +43,7 @@ static irqreturn_t msm_hdmi_irq(int irq, void > *dev_id) > struct hdmi *hdmi = dev_id; > > /* Process HPD: */ > - msm_hdmi_connector_irq(hdmi->connector); > + msm_hdmi_hpd_irq(hdmi->bridge); > > /* Process DDC: */ > msm_hdmi_i2c_irq(hdmi->i2c); > @@ -283,7 +285,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, > goto fail; > } > > - hdmi->connector = msm_hdmi_connector_init(hdmi); > + hdmi->connector = drm_bridge_connector_init(hdmi->dev, encoder); > if (IS_ERR(hdmi->connector)) { > ret = PTR_ERR(hdmi->connector); > DRM_DEV_ERROR(dev->dev, "failed to create HDMI connector: %d\n", > ret); > @@ -291,6 +293,8 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, > goto fail; > } > > + drm_connector_attach_encoder(hdmi->connector, hdmi->encoder); > + > hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); > if (hdmi->irq < 0) { > ret = hdmi->irq; > @@ -307,7 +311,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, > goto fail; > } > > - ret = msm_hdmi_hpd_enable(hdmi->connector); > + drm_bridge_connector_enable_hpd(hdmi->connector); > + > + ret = msm_hdmi_hpd_enable(hdmi->bridge); > if (ret < 0) { > DRM_DEV_ERROR(>pdev->dev, "failed to enable HPD: %d\n", ret); > goto fail; > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h > b/drivers/gpu/drm/msm/hdmi/hdmi.h > index 82261078c6b1..736f348befb3 100644 > --- a/drivers/gpu/drm/msm/hdmi/hdmi.h > +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h > @@ -114,6 +114,13 @@ struct hdmi_platform_config { > struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO]; > }; > > +struct hdmi_bridge { > + struct drm_bridge base; > + struct hdmi *hdmi; > + struct work_struct hpd_work; > +}; > +#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base) > + > void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on); > > static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data) > @@ -230,13 +237,11 @@ void msm_hdmi_audio_set_sample_rate(struct hdmi > *hdmi, int rate); > struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi); > void msm_hdmi_bridge_destroy(struct drm_bridge *bridge); > > -/* > - * hdmi connector: > - */ > - > -void msm_hdmi_connector_irq(struct drm_connector *connector); > -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi); > -int msm_hdmi_hpd_enable(struct drm_connector *connector); > +void msm_hdmi_hpd_irq(struct drm_bridge *bridge); > +enum drm_connector_status msm_hdmi_bridge_detect( > + struct drm_bridge *bridge); > +int msm_hdmi_hpd_enable(struct drm_bridge *bridge); > +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge); > > /* > * i2c adapter for ddc: > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c > b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c > index f04eb4a70f0d..211b73dddf65 100644 > --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c > +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c > @@ -5,17 +5,16 @@ > */ > > #include > +#include > > +#include "msm_kms.h" > #include "hdmi.h" > > -struct hdmi_bridge { > - struct drm_bridge base; > - struct hdmi *hdmi; > -}; > -#define to_hdmi_bridge(x)
Re: [Freedreno] [PATCH v5 7/7] drm/msm/dp: Add sc8180x DP controllers
On 2021-10-16 15:18, Bjorn Andersson wrote: The sc8180x has 2 DP and 1 eDP controllers, add support for these to the DP driver. Link: https://lore.kernel.org/linux-arm-msm/20210725042436.3967173-7-bjorn.anders...@linaro.org/ Signed-off-by: Bjorn Andersson Reviewed-by: Abhinav Kumar --- Changes since v4: - Use the MSM_DP_CONTROLLER_n enums - const the msm_dp_desc array drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 6 +++--- drivers/gpu/drm/msm/dp/dp_display.c| 11 +++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 47d5d71eb5d3..0ac6a79e8af9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -918,13 +918,13 @@ static const struct dpu_intf_cfg sc7280_intf[] = { }; static const struct dpu_intf_cfg sc8180x_intf[] = { - INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 24, 25), + INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 24, 25), INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 26, 27), INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 28, 29), /* INTF_3 is for MST, wired to INTF_DP 0 and 1, use dummy index until this is supported */ INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_DP, 999, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 30, 31), - INTF_BLK("intf_4", INTF_4, 0x6C000, INTF_DP, 1, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 20, 21), - INTF_BLK("intf_5", INTF_5, 0x6C800, INTF_DP, 2, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 22, 23), + INTF_BLK("intf_4", INTF_4, 0x6C000, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 20, 21), + INTF_BLK("intf_5", INTF_5, 0x6C800, INTF_DP, MSM_DP_CONTROLLER_2, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 22, 23), }; /* diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index d3c9d7273354..70dcd4e6d466 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -135,8 +135,19 @@ static const struct msm_dp_config sc7180_dp_cfg = { .num_descs = 1, }; +static const struct msm_dp_config sc8180x_dp_cfg = { + .descs = (const struct msm_dp_desc[]) { + [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae9, .connector_type = DRM_MODE_CONNECTOR_DisplayPort }, + [MSM_DP_CONTROLLER_1] = { .io_start = 0x0ae98000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort }, + [MSM_DP_CONTROLLER_2] = { .io_start = 0x0ae9a000, .connector_type = DRM_MODE_CONNECTOR_eDP }, + }, + .num_descs = 3, +}; + static const struct of_device_id dp_dt_match[] = { { .compatible = "qcom,sc7180-dp", .data = _dp_cfg }, + { .compatible = "qcom,sc8180x-dp", .data = _dp_cfg }, + { .compatible = "qcom,sc8180x-edp", .data = _dp_cfg }, {} };
Re: [Freedreno] [PATCH v5 5/7] drm/msm/dp: Support up to 3 DP controllers
On 2021-10-16 15:18, Bjorn Andersson wrote: Based on the removal of the g_dp_display and the movement of the priv->dp lookup into the DP code it's now possible to have multiple DP instances. In line with the other controllers in the MSM driver, introduce a per-compatible list of base addresses which is used to resolve the "instance id" for the given DP controller. This instance id is used as index in the priv->dp[] array. Then extend the initialization code to initialize struct drm_encoder for each of the registered priv->dp[] and update the logic for associating each struct msm_dp with the struct dpu_encoder_virt. A new enum is introduced to document the connection between the instances referenced in the dpu_intf_cfg array and the controllers in the DP driver and sc7180 is updated. Lastly, bump the number of struct msm_dp instances carries by priv->dp to 3, the currently known maximum number of controllers found in a Qualcomm SoC. Signed-off-by: Bjorn Andersson Reviewed-by: Abhinav Kumar --- Changes since v4: - MSM_DP_CONTROLLER_n introduced to clarify the relationship between the intf specification and the indices of the msm_dp_desc - Unnecessary parenthesis around dp->dp_display was dropped drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 +- .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66 +++ .../gpu/drm/msm/disp/msm_disp_snapshot_util.c | 8 ++- drivers/gpu/drm/msm/dp/dp_display.c | 20 -- drivers/gpu/drm/msm/msm_drv.h | 9 ++- 6 files changed, 68 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index b7f33da2799c..9cd9539a1504 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2173,7 +2173,7 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, dpu_encoder_vsync_event_handler, 0); else if (disp_info->intf_type == DRM_MODE_ENCODER_TMDS) - dpu_enc->dp = priv->dp; + dpu_enc->dp = priv->dp[disp_info->h_tile_instance[0]]; INIT_DELAYED_WORK(_enc->delayed_off_work, dpu_encoder_off_work); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 60eed3128b54..47d5d71eb5d3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -900,7 +900,7 @@ static const struct dpu_intf_cfg sdm845_intf[] = { }; static const struct dpu_intf_cfg sc7180_intf[] = { - INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), + INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27), }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index f655adbc2421..875b07e7183d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -188,6 +188,7 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) struct dentry *entry; struct drm_device *dev; struct msm_drm_private *priv; + int i; if (!p) return -EINVAL; @@ -203,8 +204,10 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) dpu_debugfs_vbif_init(dpu_kms, entry); dpu_debugfs_core_irq_init(dpu_kms, entry); - if (priv->dp) - msm_dp_debugfs_init(priv->dp, minor); + for (i = 0; i < ARRAY_SIZE(priv->dp); i++) { + if (priv->dp[i]) + msm_dp_debugfs_init(priv->dp[i], minor); + } return dpu_core_perf_debugfs_init(dpu_kms, entry); } @@ -544,35 +547,42 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, { struct drm_encoder *encoder = NULL; struct msm_display_info info; - int rc = 0; + int rc; + int i; - if (!priv->dp) - return rc; + for (i = 0; i < ARRAY_SIZE(priv->dp); i++) { + if (!priv->dp[i]) + continue; - encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS); - if (IS_ERR(encoder)) { - DPU_ERROR("encoder init failed for dsi display\n"); - return PTR_ERR(encoder); - } + encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS); + if (IS_ERR(encoder)) { + DPU_ERROR("encoder init failed for dsi display\n"); + return PTR_ERR(encoder); + } - memset(, 0, sizeof(info)); - rc =
Re: [Freedreno] [PATCH v5 4/7] drm/msm/dp: Allow attaching a drm_panel
On 2021-10-16 15:18, Bjorn Andersson wrote: eDP panels might need some power sequencing and backlight management, so make it possible to associate a drm_panel with an eDP instance and prepare and enable the panel accordingly. Now that we know which hardware instance is DP and which is eDP, parser->parse() is passed the connector_type and the parser is limited to only search for a panel in the eDP case. Signed-off-by: Bjorn Andersson Reviewed-by: Abhinav Kumar --- Changes since v4: - None drivers/gpu/drm/msm/dp/dp_display.c | 9 ++--- drivers/gpu/drm/msm/dp/dp_display.h | 1 + drivers/gpu/drm/msm/dp/dp_drm.c | 11 +++ drivers/gpu/drm/msm/dp/dp_parser.c | 30 - drivers/gpu/drm/msm/dp/dp_parser.h | 3 ++- 5 files changed, 49 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 6913970c8cf9..c663cd619925 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "msm_drv.h" #include "msm_kms.h" @@ -230,12 +231,14 @@ static int dp_display_bind(struct device *dev, struct device *master, priv = drm->dev_private; priv->dp = &(dp->dp_display); - rc = dp->parser->parse(dp->parser); + rc = dp->parser->parse(dp->parser, dp->dp_display.connector_type); if (rc) { DRM_ERROR("device tree parsing failed\n"); goto end; } + dp->dp_display.panel_bridge = dp->parser->panel_bridge; + dp->aux->drm_dev = drm; rc = dp_aux_register(dp->aux); if (rc) { @@ -822,7 +825,7 @@ static int dp_display_set_mode(struct msm_dp *dp_display, return 0; } -static int dp_display_prepare(struct msm_dp *dp) +static int dp_display_prepare(struct msm_dp *dp_display) { return 0; } @@ -896,7 +899,7 @@ static int dp_display_disable(struct dp_display_private *dp, u32 data) return 0; } -static int dp_display_unprepare(struct msm_dp *dp) +static int dp_display_unprepare(struct msm_dp *dp_display) { return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 75fcabcfbbdd..8e80e3bac394 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -15,6 +15,7 @@ struct msm_dp { struct device *codec_dev; struct drm_connector *connector; struct drm_encoder *encoder; + struct drm_bridge *panel_bridge; bool is_connected; bool audio_enabled; bool power_on; diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index f33e31523f56..76856c4ee1d6 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -5,6 +5,7 @@ #include #include +#include #include #include "msm_drv.h" @@ -160,5 +161,15 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display) drm_connector_attach_encoder(connector, dp_display->encoder); + if (dp_display->panel_bridge) { + ret = drm_bridge_attach(dp_display->encoder, + dp_display->panel_bridge, NULL, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); + if (ret < 0) { + DRM_ERROR("failed to attach panel bridge: %d\n", ret); + return ERR_PTR(ret); + } + } + return connector; } diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index 4d6e047f803d..eb6bbfbea484 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -6,6 +6,7 @@ #include #include +#include #include #include "dp_parser.h" @@ -263,7 +264,28 @@ static int dp_parser_clock(struct dp_parser *parser) return 0; } -static int dp_parser_parse(struct dp_parser *parser) +static int dp_parser_find_panel(struct dp_parser *parser) +{ + struct device *dev = >pdev->dev; + struct drm_panel *panel; + int rc; + + rc = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, , NULL); + if (rc) { + DRM_ERROR("failed to acquire DRM panel: %d\n", rc); + return rc; + } + + parser->panel_bridge = devm_drm_panel_bridge_add(dev, panel); + if (IS_ERR(parser->panel_bridge)) { + DRM_ERROR("failed to create panel bridge\n"); + return PTR_ERR(parser->panel_bridge); + } + + return 0; +} + +static int dp_parser_parse(struct dp_parser *parser, int connector_type) { int rc = 0; @@ -284,6 +306,12 @@ static int dp_parser_parse(struct dp_parser *parser) if (rc) return rc; + if (connector_type == DRM_MODE_CONNECTOR_eDP) { + rc = dp_parser_find_panel(parser); + if (rc) + return
Re: [Freedreno] [PATCH v5 3/7] drm/msm/dp: Allow specifying connector_type per controller
On 2021-10-16 15:18, Bjorn Andersson wrote: As the following patches introduced support for multiple DP blocks in a platform and some of those block might be eDP it becomes useful to be able to specify the connector type per block. Although there's only a single block at this point, the array of descs and the search in dp_display_get_desc() are introduced here to simplify the next patch, that does introduce support for multiple DP blocks. Signed-off-by: Bjorn Andersson Reviewed-by: Abhinav Kumar --- Changes since v4: - const the various struct msm_dp_desc instances - unsigned the connector_type The references to DRM_MODE_CONNECTOR_DisplayPort in dp_debug.c, that was highligted in the review of v4 has been removed in a separate patch. drivers/gpu/drm/msm/dp/dp_display.c | 43 - drivers/gpu/drm/msm/dp/dp_display.h | 1 + drivers/gpu/drm/msm/dp/dp_drm.c | 2 +- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 5d3ee5ef07c2..6913970c8cf9 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -115,8 +115,25 @@ struct dp_display_private { struct dp_audio *audio; }; +struct msm_dp_desc { + phys_addr_t io_start; + unsigned int connector_type; +}; + +struct msm_dp_config { + const struct msm_dp_desc *descs; + size_t num_descs; +}; + +static const struct msm_dp_config sc7180_dp_cfg = { + .descs = (const struct msm_dp_desc[]) { + { .io_start = 0x0ae9, .connector_type = DRM_MODE_CONNECTOR_DisplayPort }, + }, + .num_descs = 1, +}; + static const struct of_device_id dp_dt_match[] = { - {.compatible = "qcom,sc7180-dp"}, + { .compatible = "qcom,sc7180-dp", .data = _dp_cfg }, {} }; @@ -1180,10 +1197,29 @@ int dp_display_request_irq(struct msm_dp *dp_display) return 0; } +static const struct msm_dp_desc *dp_display_get_desc(struct platform_device *pdev) +{ + const struct msm_dp_config *cfg = of_device_get_match_data(>dev); + struct resource *res; + int i; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return NULL; + + for (i = 0; i < cfg->num_descs; i++) + if (cfg->descs[i].io_start == res->start) + return >descs[i]; + + dev_err(>dev, "unknown displayport instance\n"); + return NULL; +} + static int dp_display_probe(struct platform_device *pdev) { int rc = 0; struct dp_display_private *dp; + const struct msm_dp_desc *desc; if (!pdev || !pdev->dev.of_node) { DRM_ERROR("pdev not found\n"); @@ -1194,8 +1230,13 @@ static int dp_display_probe(struct platform_device *pdev) if (!dp) return -ENOMEM; + desc = dp_display_get_desc(pdev); + if (!desc) + return -EINVAL; + dp->pdev = pdev; dp->name = "drm_dp"; + dp->dp_display.connector_type = desc->connector_type; rc = dp_init_sub_modules(dp); if (rc) { diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 8b47cdabb67e..75fcabcfbbdd 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -18,6 +18,7 @@ struct msm_dp { bool is_connected; bool audio_enabled; bool power_on; + unsigned int connector_type; hdmi_codec_plugged_cb plugged_cb; diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index 764f4b81017e..f33e31523f56 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -147,7 +147,7 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display) ret = drm_connector_init(dp_display->drm_dev, connector, _connector_funcs, - DRM_MODE_CONNECTOR_DisplayPort); + dp_display->connector_type); if (ret) return ERR_PTR(ret);
Re: [Freedreno] [PATCH] drm/msm/dp: Move debugfs files into subdirectory
Hi Bjorn On 2021-10-17 09:42, Bjorn Andersson wrote: On Fri 15 Oct 16:53 PDT 2021, abhin...@codeaurora.org wrote: On 2021-10-15 16:17, Bjorn Andersson wrote: > In the cleanup path of the MSM DP driver the DP driver's debugfs files > are destroyed by invoking debugfs_remove_recursive() on debug->root, > which during initialization has been set to minor->debugfs_root. > > To allow cleaning up the DP driver's debugfs files either each dentry > needs to be kept track of or the files needs to be put in a subdirectory > which can be removed in one go. > > By choosing to put the debugfs files in a subdirectory, based on the > name of the associated connector this also solves the problem that these > names would collide as support for multiple DP instances are introduced. > > One alternative solution to the problem with colliding file names would > have been to put keep track of the individual files and put them under > the connector's debugfs directory. But while the drm_connector has been > allocated, its associated debugfs directory has not been created at the > time of initialization of the dp_debug. > > Signed-off-by: Bjorn Andersson I have been thinking about this problem ever since multi-DP has been posted :) Creating sub-directories seems right but at the moment it looks like IGT which uses these debugfs nodes doesnt check sub-directories: https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/blob/master/tools/msm_dp_compliance.c#L215 It looks for the DP debugfs nodes under /sys/kernel/debug/dri/*/ We have to fix IGT too to be able to handle multi-DP cases. I will try to come up with a proposal to address this. Till then, can we go with the other solution to keep track of the dentries? I'm afraid I don't see what you're proposing. Afaict we need one set of dp_test{type,active,data} per DP controller, so even doing this by keeping track of the dentries requires that we rename the files based on some identifier (id or connector name) - which will cause igt to break. Yes, I also thought the same that there needs to be some identifier. "To allow cleaning up the DP driver's debugfs files either each dentry needs to be kept track of or the files needs to be put in a subdirectory which can be removed in one go" I guess I misunderstood your statement in the commit text thinking that you had some other way to keep track of the dentries as it mentioned that use a subdirectory OR keep track of each dentry. As such, I think the practical path forward is that we merge the multi-DP series as currently proposed. This will not cause any issues on single-DP systems, but on multi-DP systems we will have warnings about duplicate debugfs entries in the kernel logs. Then you can figure out how to rework igt to deal with the multiple DP instances and update the dp_debug interface accordingly. Fine with me, I will take care of this. Which also implies that we should hold this patch back. But if we go that path, I think we should fix dp_debug_deinit() so that it doesn't remove /sys/kernel/debug/dri/128 when the DP driver is unloaded. Yes, lets hold this patch back till I fix multi-DP for IGT. Regards, Bjorn > --- > > This depends on > https://lore.kernel.org/linux-arm-msm/20211010030435.4000642-1-bjorn.anders...@linaro.org/ > reducing the connector from a double pointer. > > drivers/gpu/drm/msm/dp/dp_debug.c | 15 +-- > 1 file changed, 9 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c > b/drivers/gpu/drm/msm/dp/dp_debug.c > index da4323556ef3..67da4c69eca1 100644 > --- a/drivers/gpu/drm/msm/dp/dp_debug.c > +++ b/drivers/gpu/drm/msm/dp/dp_debug.c > @@ -210,26 +210,29 @@ static const struct file_operations > test_active_fops = { > static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor > *minor) > { >int rc = 0; > + char path[64]; >struct dp_debug_private *debug = container_of(dp_debug, >struct dp_debug_private, dp_debug); > > - debugfs_create_file("dp_debug", 0444, minor->debugfs_root, > + snprintf(path, sizeof(path), "msm_dp-%s", debug->connector->name); > + > + debug->root = debugfs_create_dir(path, minor->debugfs_root); > + > + debugfs_create_file("dp_debug", 0444, debug->root, >debug, _debug_fops); > >debugfs_create_file("msm_dp_test_active", 0444, > - minor->debugfs_root, > + debug->root, >debug, _active_fops); > >debugfs_create_file("msm_dp_test_data", 0444, > - minor->debugfs_root, > + debug->root, >debug, _test_data_fops); > >debugfs_create_file("msm_dp_test_type", 0444, > - minor->debugfs_root, > + debug->root, >debug, _test_type_fops); > > - debug->root = minor->debugfs_root; > - >return rc; > }
Re: [Freedreno] [PATCH] drm/msm/dp: Move debugfs files into subdirectory
On 2021-10-15 16:17, Bjorn Andersson wrote: In the cleanup path of the MSM DP driver the DP driver's debugfs files are destroyed by invoking debugfs_remove_recursive() on debug->root, which during initialization has been set to minor->debugfs_root. To allow cleaning up the DP driver's debugfs files either each dentry needs to be kept track of or the files needs to be put in a subdirectory which can be removed in one go. By choosing to put the debugfs files in a subdirectory, based on the name of the associated connector this also solves the problem that these names would collide as support for multiple DP instances are introduced. One alternative solution to the problem with colliding file names would have been to put keep track of the individual files and put them under the connector's debugfs directory. But while the drm_connector has been allocated, its associated debugfs directory has not been created at the time of initialization of the dp_debug. Signed-off-by: Bjorn Andersson I have been thinking about this problem ever since multi-DP has been posted :) Creating sub-directories seems right but at the moment it looks like IGT which uses these debugfs nodes doesnt check sub-directories: https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/blob/master/tools/msm_dp_compliance.c#L215 It looks for the DP debugfs nodes under /sys/kernel/debug/dri/*/ We have to fix IGT too to be able to handle multi-DP cases. I will try to come up with a proposal to address this. Till then, can we go with the other solution to keep track of the dentries? --- This depends on https://lore.kernel.org/linux-arm-msm/20211010030435.4000642-1-bjorn.anders...@linaro.org/ reducing the connector from a double pointer. drivers/gpu/drm/msm/dp/dp_debug.c | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index da4323556ef3..67da4c69eca1 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -210,26 +210,29 @@ static const struct file_operations test_active_fops = { static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor) { int rc = 0; + char path[64]; struct dp_debug_private *debug = container_of(dp_debug, struct dp_debug_private, dp_debug); - debugfs_create_file("dp_debug", 0444, minor->debugfs_root, + snprintf(path, sizeof(path), "msm_dp-%s", debug->connector->name); + + debug->root = debugfs_create_dir(path, minor->debugfs_root); + + debugfs_create_file("dp_debug", 0444, debug->root, debug, _debug_fops); debugfs_create_file("msm_dp_test_active", 0444, - minor->debugfs_root, + debug->root, debug, _active_fops); debugfs_create_file("msm_dp_test_data", 0444, - minor->debugfs_root, + debug->root, debug, _test_data_fops); debugfs_create_file("msm_dp_test_type", 0444, - minor->debugfs_root, + debug->root, debug, _test_type_fops); - debug->root = minor->debugfs_root; - return rc; }
Re: [Freedreno] [PATCH] drm/msm/dp: Only create debugfs for PRIMARY minor
On 2021-10-15 16:13, Bjorn Andersson wrote: dpu_kms_debugfs_init() and hence dp_debug_get() gets invoked for each minor being registered. But dp_debug_get() will allocate a new struct dp_debug for each call and this will be associated as dp->debug. As such dp_debug will create debugfs files in both the PRIMARY and the RENDER minor's debugfs directory, but only the last reference will be remembered. The only use of this reference today is in the cleanup path in dp_display_deinit_sub_modules() and the dp_debug_private object does outlive the debugfs entries in either case, so there doesn't seem to be any adverse effects of this, but per the code the current behavior is unexpected, so change it to only create dp_debug for the PRIMARY minor. If i understand correctly, today because of this, we get redundant debugfs nodes right? /sys/kernel/debug/dri//dp_debug /sys/kernel/debug/dri//dp_debug Both of these will hold the same information as they are for the same DP controller right? In that case, this is true even for the other DPU kms information too. Why not move this check one level up to dpu_kms_debugfs_init? Signed-off-by: Bjorn Andersson --- drivers/gpu/drm/msm/dp/dp_display.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 3aa67c53dbc0..06773b58bb60 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "msm_drv.h" @@ -1463,6 +1464,10 @@ void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor) dp = container_of(dp_display, struct dp_display_private, dp_display); dev = >pdev->dev; + /* Only create one set of debugfs per DP instance */ + if (minor->type != DRM_MINOR_PRIMARY) + return; + dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd, dp->link, dp->dp_display.connector, minor);
Re: [Freedreno] [PATCH 2/2] drm/msm/hdmi: switch to drm_bridge_connector
Hi Dmitry On 2021-10-14 17:11, Dmitry Baryshkov wrote: Merge old hdmi_bridge and hdmi_connector implementations. Use drm_bridge_connector instead. Can you please comment on the validation done on this change? Has basic bootup been verified on db820c as thats the only platform which shall use this. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/Makefile | 2 +- drivers/gpu/drm/msm/hdmi/hdmi.c | 12 +- drivers/gpu/drm/msm/hdmi/hdmi.h | 19 ++- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c| 81 - .../msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} | 154 ++ 5 files changed, 109 insertions(+), 159 deletions(-) rename drivers/gpu/drm/msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} (62%) diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 904535eda0c4..91b09cda8a9c 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -19,7 +19,7 @@ msm-y := \ hdmi/hdmi.o \ hdmi/hdmi_audio.o \ hdmi/hdmi_bridge.o \ - hdmi/hdmi_connector.o \ + hdmi/hdmi_hpd.o \ hdmi/hdmi_i2c.o \ hdmi/hdmi_phy.o \ hdmi/hdmi_phy_8960.o \ diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index db17a000d968..d1cf4df7188c 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -8,6 +8,8 @@ #include #include +#include + #include #include "hdmi.h" @@ -41,7 +43,7 @@ static irqreturn_t msm_hdmi_irq(int irq, void *dev_id) struct hdmi *hdmi = dev_id; /* Process HPD: */ - msm_hdmi_connector_irq(hdmi->connector); + msm_hdmi_hpd_irq(hdmi->bridge); /* Process DDC: */ msm_hdmi_i2c_irq(hdmi->i2c); @@ -283,7 +285,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, goto fail; } - hdmi->connector = msm_hdmi_connector_init(hdmi); + hdmi->connector = drm_bridge_connector_init(hdmi->dev, encoder); if (IS_ERR(hdmi->connector)) { ret = PTR_ERR(hdmi->connector); DRM_DEV_ERROR(dev->dev, "failed to create HDMI connector: %d\n", ret); @@ -291,6 +293,8 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, goto fail; } + drm_connector_attach_encoder(hdmi->connector, hdmi->encoder); + hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); if (hdmi->irq < 0) { ret = hdmi->irq; @@ -307,7 +311,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, goto fail; } - ret = msm_hdmi_hpd_enable(hdmi->connector); + drm_bridge_connector_enable_hpd(hdmi->connector); + + ret = msm_hdmi_hpd_enable(hdmi->bridge); if (ret < 0) { DRM_DEV_ERROR(>pdev->dev, "failed to enable HPD: %d\n", ret); goto fail; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index 82261078c6b1..736f348befb3 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -114,6 +114,13 @@ struct hdmi_platform_config { struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO]; }; +struct hdmi_bridge { + struct drm_bridge base; + struct hdmi *hdmi; + struct work_struct hpd_work; +}; +#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base) + void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on); static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data) @@ -230,13 +237,11 @@ void msm_hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate); struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi); void msm_hdmi_bridge_destroy(struct drm_bridge *bridge); -/* - * hdmi connector: - */ - -void msm_hdmi_connector_irq(struct drm_connector *connector); -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi); -int msm_hdmi_hpd_enable(struct drm_connector *connector); +void msm_hdmi_hpd_irq(struct drm_bridge *bridge); +enum drm_connector_status msm_hdmi_bridge_detect( + struct drm_bridge *bridge); +int msm_hdmi_hpd_enable(struct drm_bridge *bridge); +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge); /* * i2c adapter for ddc: diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index f04eb4a70f0d..211b73dddf65 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -5,17 +5,16 @@ */ #include +#include +#include "msm_kms.h" #include "hdmi.h" -struct hdmi_bridge { - struct drm_bridge base; - struct hdmi *hdmi; -}; -#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base) - void msm_hdmi_bridge_destroy(struct drm_bridge *bridge) { + struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); + + msm_hdmi_hpd_disable(hdmi_bridge); } static void msm_hdmi_power_on(struct drm_bridge *bridge) @@ -251,14 +250,76 @@ static void msm_hdmi_bridge_mode_set(struct
Re: [Freedreno] [PATCH 1/2] drm/msm/hdmi: use bulk regulator API
On 2021-10-14 17:10, Dmitry Baryshkov wrote: Switch to using bulk regulator API instead of hand coding loops. Nice cleanup! Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/hdmi/hdmi.c | 34 +++ drivers/gpu/drm/msm/hdmi/hdmi.h | 6 ++-- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c| 20 - drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 24 ++-- drivers/gpu/drm/msm/hdmi/hdmi_phy.c | 33 -- 5 files changed, 40 insertions(+), 77 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 737453b6e596..db17a000d968 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -154,19 +154,13 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) ret = -ENOMEM; goto fail; } - for (i = 0; i < config->hpd_reg_cnt; i++) { - struct regulator *reg; - - reg = devm_regulator_get(>dev, - config->hpd_reg_names[i]); - if (IS_ERR(reg)) { - ret = PTR_ERR(reg); - DRM_DEV_ERROR(>dev, "failed to get hpd regulator: %s (%d)\n", - config->hpd_reg_names[i], ret); - goto fail; - } + for (i = 0; i < config->hpd_reg_cnt; i++) + hdmi->hpd_regs[i].supply = config->hpd_reg_names[i]; - hdmi->hpd_regs[i] = reg; + ret = devm_regulator_bulk_get(>dev, config->hpd_reg_cnt, hdmi->hpd_regs); + if (ret) { + DRM_DEV_ERROR(>dev, "failed to get hpd regulator: %d\n", ret); + goto fail; } hdmi->pwr_regs = devm_kcalloc(>dev, @@ -177,19 +171,11 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) ret = -ENOMEM; goto fail; } - for (i = 0; i < config->pwr_reg_cnt; i++) { - struct regulator *reg; - reg = devm_regulator_get(>dev, - config->pwr_reg_names[i]); - if (IS_ERR(reg)) { - ret = PTR_ERR(reg); - DRM_DEV_ERROR(>dev, "failed to get pwr regulator: %s (%d)\n", - config->pwr_reg_names[i], ret); - goto fail; - } - - hdmi->pwr_regs[i] = reg; + ret = devm_regulator_bulk_get(>dev, config->pwr_reg_cnt, hdmi->pwr_regs); + if (ret) { + DRM_DEV_ERROR(>dev, "failed to get pwr regulator: %d\n", ret); + goto fail; } hdmi->hpd_clks = devm_kcalloc(>dev, diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index d0b84f0abee1..82261078c6b1 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -56,8 +56,8 @@ struct hdmi { void __iomem *qfprom_mmio; phys_addr_t mmio_phy_addr; - struct regulator **hpd_regs; - struct regulator **pwr_regs; + struct regulator_bulk_data *hpd_regs; + struct regulator_bulk_data *pwr_regs; struct clk **hpd_clks; struct clk **pwr_clks; @@ -163,7 +163,7 @@ struct hdmi_phy { void __iomem *mmio; struct hdmi_phy_cfg *cfg; const struct hdmi_phy_funcs *funcs; - struct regulator **regs; + struct regulator_bulk_data *regs; struct clk **clks; }; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 6e380db9287b..f04eb4a70f0d 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -28,13 +28,9 @@ static void msm_hdmi_power_on(struct drm_bridge *bridge) pm_runtime_get_sync(>pdev->dev); - for (i = 0; i < config->pwr_reg_cnt; i++) { - ret = regulator_enable(hdmi->pwr_regs[i]); - if (ret) { - DRM_DEV_ERROR(dev->dev, "failed to enable pwr regulator: %s (%d)\n", - config->pwr_reg_names[i], ret); - } - } + ret = regulator_bulk_enable(config->pwr_reg_cnt, hdmi->pwr_regs); + if (ret) + DRM_DEV_ERROR(dev->dev, "failed to enable pwr regulator: %d\n", ret); if (config->pwr_clk_cnt > 0) { DBG("pixclock: %lu", hdmi->pixclock); @@ -70,13 +66,9 @@ static void power_off(struct drm_bridge *bridge) for (i = 0; i < config->pwr_clk_cnt; i++) clk_disable_unprepare(hdmi->pwr_clks[i]); - for (i = 0; i < config->pwr_reg_cnt; i++) { - ret = regulator_disable(hdmi->pwr_regs[i]); - if (ret) { - DRM_DEV_ERROR(dev->dev, "failed to disable pwr regulator: %s (%d)\n", - config->pwr_reg_names[i], ret); - } - } + ret =
Re: [Freedreno] [PATCH 0/3] drm/msm: drop old eDP support
Hi Dmitry No concerns from our side to drop this. Reviewed-by: Abhinav Kumar for the series. Thanks Abhinav On 2021-10-01 09:50, Dmitry Baryshkov wrote: MSM DRM driver has support for eDP block present on MSM 8x74/8x84 SoC families. However since addition back in 2015 this driver received only generic fixes. No actual devices with these SoCs supported upstream (or by the community) seem to support eDP panels. Judging from downstream kernels the eDP was present only on MSM8974 LIQUID or on APQ8084 CDP. Remove this driver. Dmitry Baryshkov (3): drm/msm/mdp5: drop eDP support drm/msm/edp: drop old eDP support dt-bindings: display/msm: remove edp.txt .../devicetree/bindings/display/msm/edp.txt| 56 - drivers/gpu/drm/msm/Makefile |6 - drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 17 +- drivers/gpu/drm/msm/edp/edp.c | 198 --- drivers/gpu/drm/msm/edp/edp.h | 77 -- drivers/gpu/drm/msm/edp/edp.xml.h | 388 -- drivers/gpu/drm/msm/edp/edp_aux.c | 265 drivers/gpu/drm/msm/edp/edp_bridge.c | 111 -- drivers/gpu/drm/msm/edp/edp_connector.c| 132 -- drivers/gpu/drm/msm/edp/edp_ctrl.c | 1375 drivers/gpu/drm/msm/edp/edp_phy.c | 98 -- drivers/gpu/drm/msm/msm_drv.c |2 - drivers/gpu/drm/msm/msm_drv.h | 12 - 13 files changed, 1 insertion(+), 2736 deletions(-) delete mode 100644 Documentation/devicetree/bindings/display/msm/edp.txt delete mode 100644 drivers/gpu/drm/msm/edp/edp.c delete mode 100644 drivers/gpu/drm/msm/edp/edp.h delete mode 100644 drivers/gpu/drm/msm/edp/edp.xml.h delete mode 100644 drivers/gpu/drm/msm/edp/edp_aux.c delete mode 100644 drivers/gpu/drm/msm/edp/edp_bridge.c delete mode 100644 drivers/gpu/drm/msm/edp/edp_connector.c delete mode 100644 drivers/gpu/drm/msm/edp/edp_ctrl.c delete mode 100644 drivers/gpu/drm/msm/edp/edp_phy.c
Re: [Freedreno] [PATCH] drm/msm/dp: Use the connector passed to dp_debug_get()
On 2021-10-12 16:38, Bjorn Andersson wrote: On Tue 12 Oct 16:03 PDT 2021, abhin...@codeaurora.org wrote: On 2021-10-09 20:04, Bjorn Andersson wrote: > The debugfs code is provided an array of a single drm_connector. Then to > access the connector, the list of all connectors of the DRM device is > traversed and all non-DisplayPort connectors are skipped, to find the > one and only DisplayPort connector. > > But as we move to support multiple DisplayPort controllers this will now > find multiple connectors and has no way to distinguish them. > > Pass the single connector to dp_debug_get() and use this in the debugfs > functions instead, both to simplify the code and the support the > multiple instances. > Change itself is fine, hence Reviewed-by: Abhinav Kumar Thanks. What has to be checked now is now to create multiple DP nodes for multi-DP cases. Today, the debug node will be created only once : https://gitlab.freedesktop.org/drm/msm/-/blob/msm-next/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c#L206 This also needs to be expanded for multi-DP to make the solution complete. In my multi-DP support patch I end up invoking msm_dp_debugfs_init() for each of the DP/eDP instances and in its current form the first one gets registered and any others will fail because of the resulting name collision. This patch came as a byproduct of the effort of addressing that problem. Regards, Bjorn Ah, okay. Yes i see the part you are referring to in https://patchwork.freedesktop.org/patch/457667/: @@ -203,8 +204,10 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) dpu_debugfs_vbif_init(dpu_kms, entry); dpu_debugfs_core_irq_init(dpu_kms, entry); - if (priv->dp) - msm_dp_debugfs_init(priv->dp, minor); + for (i = 0; i < ARRAY_SIZE(priv->dp); i++) { + if (priv->dp[i]) + msm_dp_debugfs_init(priv->dp[i], minor); + } That clarifies it. Thanks. > Signed-off-by: Bjorn Andersson > --- > drivers/gpu/drm/msm/dp/dp_debug.c | 131 ++-- > drivers/gpu/drm/msm/dp/dp_debug.h | 2 +- > drivers/gpu/drm/msm/dp/dp_display.c | 2 +- > 3 files changed, 46 insertions(+), 89 deletions(-) > > diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c > b/drivers/gpu/drm/msm/dp/dp_debug.c > index af709d93bb9f..da4323556ef3 100644 > --- a/drivers/gpu/drm/msm/dp/dp_debug.c > +++ b/drivers/gpu/drm/msm/dp/dp_debug.c > @@ -24,7 +24,7 @@ struct dp_debug_private { >struct dp_usbpd *usbpd; >struct dp_link *link; >struct dp_panel *panel; > - struct drm_connector **connector; > + struct drm_connector *connector; >struct device *dev; >struct drm_device *drm_dev; > > @@ -97,59 +97,35 @@ DEFINE_SHOW_ATTRIBUTE(dp_debug); > > static int dp_test_data_show(struct seq_file *m, void *data) > { > - struct drm_device *dev; > - struct dp_debug_private *debug; > - struct drm_connector *connector; > - struct drm_connector_list_iter conn_iter; > + const struct dp_debug_private *debug = m->private; > + const struct drm_connector *connector = debug->connector; >u32 bpc; > > - debug = m->private; > - dev = debug->drm_dev; > - drm_connector_list_iter_begin(dev, _iter); > - drm_for_each_connector_iter(connector, _iter) { > - > - if (connector->connector_type != > - DRM_MODE_CONNECTOR_DisplayPort) > - continue; > - > - if (connector->status == connector_status_connected) { > - bpc = debug->link->test_video.test_bit_depth; > - seq_printf(m, "hdisplay: %d\n", > - debug->link->test_video.test_h_width); > - seq_printf(m, "vdisplay: %d\n", > - debug->link->test_video.test_v_height); > - seq_printf(m, "bpc: %u\n", > - dp_link_bit_depth_to_bpc(bpc)); > - } else > - seq_puts(m, "0"); > + if (connector->status == connector_status_connected) { > + bpc = debug->link->test_video.test_bit_depth; > + seq_printf(m, "hdisplay: %d\n", > + debug->link->test_video.test_h_width); > + seq_printf(m, "vdisplay: %d\n", > + debug->link->test_video.test_v_height); > + seq_printf(m, "bpc: %u\n", > + dp_link_bit_depth_to_bpc(bpc)); > + } else { > + seq_puts(m, "0"); >} > > - drm_connector_list_iter_end(_iter); > - >return 0; > } > DEFINE_SHOW_ATTRIBUTE(dp_test_data); > > static int dp_test_type_show(struct seq_file *m, void *data) > { > - struct dp_debug_private *debug = m->private; > - struct drm_device *dev = debug->drm_dev; > - struct drm_connector *connector; > - struct drm_connector_list_iter conn_iter; > - > - drm_connector_list_iter_begin(dev, _iter); > - drm_for_each_connector_iter(connector, _iter) { > - > - if
Re: [PATCH] drm/msm/dp: Use the connector passed to dp_debug_get()
On 2021-10-09 20:04, Bjorn Andersson wrote: The debugfs code is provided an array of a single drm_connector. Then to access the connector, the list of all connectors of the DRM device is traversed and all non-DisplayPort connectors are skipped, to find the one and only DisplayPort connector. But as we move to support multiple DisplayPort controllers this will now find multiple connectors and has no way to distinguish them. Pass the single connector to dp_debug_get() and use this in the debugfs functions instead, both to simplify the code and the support the multiple instances. Change itself is fine, hence Reviewed-by: Abhinav Kumar What has to be checked now is now to create multiple DP nodes for multi-DP cases. Today, the debug node will be created only once : https://gitlab.freedesktop.org/drm/msm/-/blob/msm-next/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c#L206 This also needs to be expanded for multi-DP to make the solution complete. Signed-off-by: Bjorn Andersson --- drivers/gpu/drm/msm/dp/dp_debug.c | 131 ++-- drivers/gpu/drm/msm/dp/dp_debug.h | 2 +- drivers/gpu/drm/msm/dp/dp_display.c | 2 +- 3 files changed, 46 insertions(+), 89 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index af709d93bb9f..da4323556ef3 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -24,7 +24,7 @@ struct dp_debug_private { struct dp_usbpd *usbpd; struct dp_link *link; struct dp_panel *panel; - struct drm_connector **connector; + struct drm_connector *connector; struct device *dev; struct drm_device *drm_dev; @@ -97,59 +97,35 @@ DEFINE_SHOW_ATTRIBUTE(dp_debug); static int dp_test_data_show(struct seq_file *m, void *data) { - struct drm_device *dev; - struct dp_debug_private *debug; - struct drm_connector *connector; - struct drm_connector_list_iter conn_iter; + const struct dp_debug_private *debug = m->private; + const struct drm_connector *connector = debug->connector; u32 bpc; - debug = m->private; - dev = debug->drm_dev; - drm_connector_list_iter_begin(dev, _iter); - drm_for_each_connector_iter(connector, _iter) { - - if (connector->connector_type != - DRM_MODE_CONNECTOR_DisplayPort) - continue; - - if (connector->status == connector_status_connected) { - bpc = debug->link->test_video.test_bit_depth; - seq_printf(m, "hdisplay: %d\n", - debug->link->test_video.test_h_width); - seq_printf(m, "vdisplay: %d\n", - debug->link->test_video.test_v_height); - seq_printf(m, "bpc: %u\n", - dp_link_bit_depth_to_bpc(bpc)); - } else - seq_puts(m, "0"); + if (connector->status == connector_status_connected) { + bpc = debug->link->test_video.test_bit_depth; + seq_printf(m, "hdisplay: %d\n", + debug->link->test_video.test_h_width); + seq_printf(m, "vdisplay: %d\n", + debug->link->test_video.test_v_height); + seq_printf(m, "bpc: %u\n", + dp_link_bit_depth_to_bpc(bpc)); + } else { + seq_puts(m, "0"); } - drm_connector_list_iter_end(_iter); - return 0; } DEFINE_SHOW_ATTRIBUTE(dp_test_data); static int dp_test_type_show(struct seq_file *m, void *data) { - struct dp_debug_private *debug = m->private; - struct drm_device *dev = debug->drm_dev; - struct drm_connector *connector; - struct drm_connector_list_iter conn_iter; - - drm_connector_list_iter_begin(dev, _iter); - drm_for_each_connector_iter(connector, _iter) { - - if (connector->connector_type != - DRM_MODE_CONNECTOR_DisplayPort) - continue; + const struct dp_debug_private *debug = m->private; + const struct drm_connector *connector = debug->connector; - if (connector->status == connector_status_connected) - seq_printf(m, "%02x", DP_TEST_LINK_VIDEO_PATTERN); - else - seq_puts(m, "0"); - } - drm_connector_list_iter_end(_iter); + if (connector->status == connector_status_connected) + seq_printf(m, "%02x", DP_TEST_LINK_VIDEO_PATTERN); + else + seq_puts(m, "0"); return 0; } @@ -161,14 +137,12 @@ static ssize_t dp_test_active_write(struct file *file, { char *input_buffer; int status = 0; - struct dp_debug_private *debug; - struct drm_device *dev; - struct
Re: [Freedreno] [PATCH v2] drm/msm/dsi: Use division result from div_u64_rem in 7nm and 14nm PLL
On 2021-10-11 13:16, Marijn Suijten wrote: div_u64_rem provides the result of the division and additionally the remainder; don't use this function to solely calculate the remainder while calculating the division again with div_u64. A similar improvement was applied earlier to the 10nm pll in 5c191fef4ce2 ("drm/msm/dsi_pll_10nm: Fix dividing the same numbers twice"). Signed-off-by: Marijn Suijten Reviewed-by: Abhinav Kumar --- Changes in v2: - Corrected two typos in the first commit-message sentence. drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 4 +--- drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c index 9a959a5dcc1e..de3c6556a587 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c @@ -215,9 +215,7 @@ static void pll_14nm_dec_frac_calc(struct dsi_pll_14nm *pll, struct dsi_pll_conf DBG("vco_clk_rate=%lld ref_clk_rate=%lld", vco_clk_rate, fref); dec_start_multiple = div_u64(vco_clk_rate * multiplier, fref); - div_u64_rem(dec_start_multiple, multiplier, _frac_start); - - dec_start = div_u64(dec_start_multiple, multiplier); + dec_start = div_u64_rem(dec_start_multiple, multiplier, _frac_start); pconf->dec_start = (u32)dec_start; pconf->div_frac_start = div_frac_start; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c index 9f7c408325ba..36eb6109cb88 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -114,9 +114,7 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll, struct dsi_pll_config multiplier = 1 << FRAC_BITS; dec_multiple = div_u64(pll_freq * multiplier, divider); - div_u64_rem(dec_multiple, multiplier, ); - - dec = div_u64(dec_multiple, multiplier); + dec = div_u64_rem(dec_multiple, multiplier, ); if (!(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1)) config->pll_clock_inverters = 0x28; -- 2.33.0
Re: [PATCH v4 5/7] drm/msm/dp: Support up to 3 DP controllers
Hi Bjorn and Stephen On 2021-10-06 13:39, Bjorn Andersson wrote: On Wed 06 Oct 11:59 PDT 2021, Stephen Boyd wrote: Quoting Bjorn Andersson (2021-10-06 11:05:09) > On Wed 06 Oct 10:19 PDT 2021, Stephen Boyd wrote: > > > Quoting Bjorn Andersson (2021-10-06 10:07:17) > > > On Tue 05 Oct 21:26 PDT 2021, Stephen Boyd wrote: > > > > > > > Quoting Bjorn Andersson (2021-10-05 19:37:52) > > > > > On Tue 05 Oct 19:06 PDT 2021, Stephen Boyd wrote: > > > > > > > > > > > Quoting Bjorn Andersson (2021-10-05 18:43:16) > > > > > > > On Tue 05 Oct 17:43 PDT 2021, Stephen Boyd wrote: > > > > > > > > > > > > > > > Quoting Bjorn Andersson (2021-10-05 16:13:21) > > > > > > > > > diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > > index bdaf227f05dc..674cddfee5b0 100644 > > > > > > > > > --- a/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > > +++ b/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > > @@ -1233,7 +1239,7 @@ static int dp_display_probe(struct platform_device *pdev) > > > > > > > > > if (!dp) > > > > > > > > > return -ENOMEM; > > > > > > > > > > > > > > > > > > - desc = dp_display_get_desc(pdev); > > > > > > > > > + desc = dp_display_get_desc(pdev, >id); > > > > > > > > > > > > > > > > I'm sad that dp->id has to match the number in the SoC specific > > > > > > > > dpu_intf_cfg array in drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c > > > > > > > > still. Is there any way we can avoid that? Also, notice how those arrays > > > > > > > > already have INTF_DP macros, which makes me think that it may be better > > > > > > > > to connect this to those arrays instead of making an msm_dp_desc > > > > > > > > structure and then make sure the 'type' member matches a connector > > > > > > > > type number. Otherwise this code is super fragile. > > > > > > > > > > > > > > > > > > > > > > I'm afraid I don't understand what you're proposing. Or which part you > > > > > > > consider fragile, the indices of the INTF_DP instances aren't going to > > > > > > > move around... > > > > > > > > > > > > > > I have N instances of the DP driver that I need to match to N entries > > > > > > > from the platform specific intf array, I need some stable reference > > > > > > > between them. When I started this journey I figured I could rely on the > > > > > > > of_graph between the DPU and the interface controllers, but the values > > > > > > > used there today are just bogus, so that was a no go. > > > > > > > > > > > > > > We can use whatever, as long as _dpu_kms_initialize_displayport() can > > > > > > > come up with an identifier to put in h_tile_instance[0] so that > > > > > > > dpu_encoder_setup_display() can find the relevant INTF. > > > > > > > > > > > > > > > > > > > To make it more concrete we can look at sc7180 > > > > > > > > > > > > static const struct dpu_intf_cfg sc7180_intf[] = { > > > > > > INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, > > > > > > INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), > > > > > > ^ > > > > > > | > > > > > > > > > > > > intf0 is irrelevant. Also the address is irrelevant. But here we have a > > > > > > zero, the number after INTF_DP, and that is very relevant. That number > > > > > > needs to match the dp->id. Somewhere we have a match between > > > > > > controller_id and dp->id in the code. > > > > > > > > > > That number (the 0, not INTF_0) is what the code matches against dp->id > > > > > in _dpu_kms_initialize_displayport(), in order to figure out that this > > > > > is INTF_0 in dpu_encoder_setup_display(). > > > > > > > > > > I.e. look at the sc8180x patch: > > > > > > > > > > INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 24, 25), > > > > > INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 26, 27), > > > > > INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 28, 29), > > > > > /* INTF_3 is for MST, wired to INTF_DP 0 and 1, use dummy index until this is supported */ > > > > > INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_DP, 999, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 30, 31), > > > > > INTF_BLK("intf_4", INTF_4, 0x6C000, INTF_DP, 1, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 20, 21), > > > > > INTF_BLK("intf_5", INTF_5, 0x6C800, INTF_DP, 2, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 22, 23), > > > > > > > > > > Where the DP driver defines the 3 controllers with dp->id of 0, 1 and 2, > > > > > which the DPU code will match against to INTF_0, INTF_4 and INTF_5. > > > > > > > > > > > > > Yep. I'm saying that having to make that number in this intf array match > > > > the order of the register mapping descriptor array is fragile. Why can't > > > > we indicate the interface is DP or eDP with INTF_DP or INTF_EDP and then > > > > map from
Re: [Freedreno] [PATCH v4 4/7] drm/msm/dp: Allow attaching a drm_panel
On 2021-10-05 19:09, Bjorn Andersson wrote: On Tue 05 Oct 17:35 PDT 2021, abhin...@codeaurora.org wrote: Hi Bjorn On 2021-10-05 16:13, Bjorn Andersson wrote: > eDP panels might need some power sequencing and backlight management, > so make it possible to associate a drm_panel with an eDP instance and > prepare and enable the panel accordingly. > > Now that we know which hardware instance is DP and which is eDP, > parser->parse() is passed the connector_type and the parser is limited > to only search for a panel in the eDP case. > > Signed-off-by: Bjorn Andersson > --- > > Changes since v3: > - Previously posted separately, now added to series > - Make the search for a panel conditional on it being an eDP connector > - Move the search to of_graph port 1 (was 2 to distinguish from DP > link to USB-C connector) > > drivers/gpu/drm/msm/dp/dp_display.c | 9 ++--- > drivers/gpu/drm/msm/dp/dp_display.h | 1 + > drivers/gpu/drm/msm/dp/dp_drm.c | 11 +++ > drivers/gpu/drm/msm/dp/dp_parser.c | 30 - > drivers/gpu/drm/msm/dp/dp_parser.h | 3 ++- > 5 files changed, 49 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/msm/dp/dp_display.c > b/drivers/gpu/drm/msm/dp/dp_display.c > index eaf08f9e7d87..bdaf227f05dc 100644 > --- a/drivers/gpu/drm/msm/dp/dp_display.c > +++ b/drivers/gpu/drm/msm/dp/dp_display.c > @@ -10,6 +10,7 @@ > #include > #include > #include > +#include > > #include "msm_drv.h" > #include "msm_kms.h" > @@ -230,12 +231,14 @@ static int dp_display_bind(struct device *dev, > struct device *master, >priv = drm->dev_private; >priv->dp = &(dp->dp_display); > > - rc = dp->parser->parse(dp->parser); > + rc = dp->parser->parse(dp->parser, dp->dp_display.connector_type); >if (rc) { >DRM_ERROR("device tree parsing failed\n"); >goto end; >} > > + dp->dp_display.panel_bridge = dp->parser->panel_bridge; > + >dp->aux->drm_dev = drm; >rc = dp_aux_register(dp->aux); >if (rc) { > @@ -822,7 +825,7 @@ static int dp_display_set_mode(struct msm_dp > *dp_display, >return 0; > } > > -static int dp_display_prepare(struct msm_dp *dp) > +static int dp_display_prepare(struct msm_dp *dp_display) > { >return 0; > } > @@ -896,7 +899,7 @@ static int dp_display_disable(struct > dp_display_private *dp, u32 data) >return 0; > } > > -static int dp_display_unprepare(struct msm_dp *dp) > +static int dp_display_unprepare(struct msm_dp *dp_display) > { >return 0; > } > diff --git a/drivers/gpu/drm/msm/dp/dp_display.h > b/drivers/gpu/drm/msm/dp/dp_display.h > index 02999408c052..24aefca66029 100644 > --- a/drivers/gpu/drm/msm/dp/dp_display.h > +++ b/drivers/gpu/drm/msm/dp/dp_display.h > @@ -15,6 +15,7 @@ struct msm_dp { >struct device *codec_dev; >struct drm_connector *connector; >struct drm_encoder *encoder; > + struct drm_bridge *panel_bridge; >bool is_connected; >bool audio_enabled; >bool power_on; > diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c > b/drivers/gpu/drm/msm/dp/dp_drm.c > index f33e31523f56..76856c4ee1d6 100644 > --- a/drivers/gpu/drm/msm/dp/dp_drm.c > +++ b/drivers/gpu/drm/msm/dp/dp_drm.c > @@ -5,6 +5,7 @@ > > #include > #include > +#include > #include > > #include "msm_drv.h" > @@ -160,5 +161,15 @@ struct drm_connector > *dp_drm_connector_init(struct msm_dp *dp_display) > >drm_connector_attach_encoder(connector, dp_display->encoder); > > + if (dp_display->panel_bridge) { > + ret = drm_bridge_attach(dp_display->encoder, > + dp_display->panel_bridge, NULL, > + DRM_BRIDGE_ATTACH_NO_CONNECTOR); > + if (ret < 0) { > + DRM_ERROR("failed to attach panel bridge: %d\n", ret); > + return ERR_PTR(ret); > + } > + } > + >return connector; > } > diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c > b/drivers/gpu/drm/msm/dp/dp_parser.c > index 4d6e047f803d..eb6bbfbea484 100644 > --- a/drivers/gpu/drm/msm/dp/dp_parser.c > +++ b/drivers/gpu/drm/msm/dp/dp_parser.c > @@ -6,6 +6,7 @@ > #include > #include > > +#include > #include > > #include "dp_parser.h" > @@ -263,7 +264,28 @@ static int dp_parser_clock(struct dp_parser > *parser) >return 0; > } > > -static int dp_parser_parse(struct dp_parser *parser) > +static int dp_parser_find_panel(struct dp_parser *parser) > +{ > + struct device *dev = >pdev->dev; > + struct drm_panel *panel; > + int rc; > + > + rc = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, , NULL); > + if (rc) { > + DRM_ERROR("failed to acquire DRM panel: %d\n", rc); > + return rc; > + } > + > + parser->panel_bridge = devm_drm_panel_bridge_add(dev, panel); > + if (IS_ERR(parser->panel_bridge)) { > + DRM_ERROR("failed to create panel bridge\n"); > + return PTR_ERR(parser->panel_bridge); > + } When we add a bridge using devm_drm_panel_bridge_add(), it will
Re: [Freedreno] [PATCH v4 4/7] drm/msm/dp: Allow attaching a drm_panel
Hi Bjorn On 2021-10-05 16:13, Bjorn Andersson wrote: eDP panels might need some power sequencing and backlight management, so make it possible to associate a drm_panel with an eDP instance and prepare and enable the panel accordingly. Now that we know which hardware instance is DP and which is eDP, parser->parse() is passed the connector_type and the parser is limited to only search for a panel in the eDP case. Signed-off-by: Bjorn Andersson --- Changes since v3: - Previously posted separately, now added to series - Make the search for a panel conditional on it being an eDP connector - Move the search to of_graph port 1 (was 2 to distinguish from DP link to USB-C connector) drivers/gpu/drm/msm/dp/dp_display.c | 9 ++--- drivers/gpu/drm/msm/dp/dp_display.h | 1 + drivers/gpu/drm/msm/dp/dp_drm.c | 11 +++ drivers/gpu/drm/msm/dp/dp_parser.c | 30 - drivers/gpu/drm/msm/dp/dp_parser.h | 3 ++- 5 files changed, 49 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index eaf08f9e7d87..bdaf227f05dc 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "msm_drv.h" #include "msm_kms.h" @@ -230,12 +231,14 @@ static int dp_display_bind(struct device *dev, struct device *master, priv = drm->dev_private; priv->dp = &(dp->dp_display); - rc = dp->parser->parse(dp->parser); + rc = dp->parser->parse(dp->parser, dp->dp_display.connector_type); if (rc) { DRM_ERROR("device tree parsing failed\n"); goto end; } + dp->dp_display.panel_bridge = dp->parser->panel_bridge; + dp->aux->drm_dev = drm; rc = dp_aux_register(dp->aux); if (rc) { @@ -822,7 +825,7 @@ static int dp_display_set_mode(struct msm_dp *dp_display, return 0; } -static int dp_display_prepare(struct msm_dp *dp) +static int dp_display_prepare(struct msm_dp *dp_display) { return 0; } @@ -896,7 +899,7 @@ static int dp_display_disable(struct dp_display_private *dp, u32 data) return 0; } -static int dp_display_unprepare(struct msm_dp *dp) +static int dp_display_unprepare(struct msm_dp *dp_display) { return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 02999408c052..24aefca66029 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -15,6 +15,7 @@ struct msm_dp { struct device *codec_dev; struct drm_connector *connector; struct drm_encoder *encoder; + struct drm_bridge *panel_bridge; bool is_connected; bool audio_enabled; bool power_on; diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index f33e31523f56..76856c4ee1d6 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -5,6 +5,7 @@ #include #include +#include #include #include "msm_drv.h" @@ -160,5 +161,15 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display) drm_connector_attach_encoder(connector, dp_display->encoder); + if (dp_display->panel_bridge) { + ret = drm_bridge_attach(dp_display->encoder, + dp_display->panel_bridge, NULL, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); + if (ret < 0) { + DRM_ERROR("failed to attach panel bridge: %d\n", ret); + return ERR_PTR(ret); + } + } + return connector; } diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index 4d6e047f803d..eb6bbfbea484 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -6,6 +6,7 @@ #include #include +#include #include #include "dp_parser.h" @@ -263,7 +264,28 @@ static int dp_parser_clock(struct dp_parser *parser) return 0; } -static int dp_parser_parse(struct dp_parser *parser) +static int dp_parser_find_panel(struct dp_parser *parser) +{ + struct device *dev = >pdev->dev; + struct drm_panel *panel; + int rc; + + rc = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, , NULL); + if (rc) { + DRM_ERROR("failed to acquire DRM panel: %d\n", rc); + return rc; + } + + parser->panel_bridge = devm_drm_panel_bridge_add(dev, panel); + if (IS_ERR(parser->panel_bridge)) { + DRM_ERROR("failed to create panel bridge\n"); + return PTR_ERR(parser->panel_bridge); + } When we add a bridge using devm_drm_panel_bridge_add(), it will register with default bridge functions which is fine because we need the panel power to be controlled here. 140 static const struct drm_bridge_funcs
Re: [Freedreno] [PATCH v3 4/5] drm/msm/dp: Store each subblock in the io region
On 2021-10-01 10:43, Bjorn Andersson wrote: Not all platforms has DP_P0 at offset 0x1000 from the beginning of the DP block. So split the dss_io_data memory region into a set of sub-regions, to make it possible in the next patch to specify each of the sub-regions individually. Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson Reviewed-by: Abhinav Kumar --- Changes since v2: - Skipped the unnecessary reorder in struct dss_io_region drivers/gpu/drm/msm/dp/dp_catalog.c | 64 + drivers/gpu/drm/msm/dp/dp_parser.c | 28 +++-- drivers/gpu/drm/msm/dp/dp_parser.h | 9 +++- 3 files changed, 53 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index cc2bb8295329..6ae9b29044b6 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -24,15 +24,6 @@ #define DP_INTERRUPT_STATUS_ACK_SHIFT 1 #define DP_INTERRUPT_STATUS_MASK_SHIFT 2 -#define MSM_DP_CONTROLLER_AHB_OFFSET 0x -#define MSM_DP_CONTROLLER_AHB_SIZE 0x0200 -#define MSM_DP_CONTROLLER_AUX_OFFSET 0x0200 -#define MSM_DP_CONTROLLER_AUX_SIZE 0x0200 -#define MSM_DP_CONTROLLER_LINK_OFFSET 0x0400 -#define MSM_DP_CONTROLLER_LINK_SIZE0x0C00 -#define MSM_DP_CONTROLLER_P0_OFFSET0x1000 -#define MSM_DP_CONTROLLER_P0_SIZE 0x0400 - #define DP_INTERRUPT_STATUS1 \ (DP_INTR_AUX_I2C_DONE| \ DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \ @@ -66,82 +57,77 @@ void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct msm_disp_state *d { struct dp_catalog_private *catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog); + struct dss_io_data *dss = >io->dp_controller; - msm_disp_snapshot_add_block(disp_state, catalog->io->dp_controller.len, - catalog->io->dp_controller.base, "dp_ctrl"); + msm_disp_snapshot_add_block(disp_state, dss->ahb.len, dss->ahb.base, "dp_ahb"); + msm_disp_snapshot_add_block(disp_state, dss->aux.len, dss->aux.base, "dp_aux"); + msm_disp_snapshot_add_block(disp_state, dss->link.len, dss->link.base, "dp_link"); + msm_disp_snapshot_add_block(disp_state, dss->p0.len, dss->p0.base, "dp_p0"); } I like this part, devcoredump will look pretty clean and well separated with this. static inline u32 dp_read_aux(struct dp_catalog_private *catalog, u32 offset) { - offset += MSM_DP_CONTROLLER_AUX_OFFSET; - return readl_relaxed(catalog->io->dp_controller.base + offset); + return readl_relaxed(catalog->io->dp_controller.aux.base + offset); } static inline void dp_write_aux(struct dp_catalog_private *catalog, u32 offset, u32 data) { - offset += MSM_DP_CONTROLLER_AUX_OFFSET; /* * To make sure aux reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - writel(data, catalog->io->dp_controller.base + offset); + writel(data, catalog->io->dp_controller.aux.base + offset); } static inline u32 dp_read_ahb(struct dp_catalog_private *catalog, u32 offset) { - offset += MSM_DP_CONTROLLER_AHB_OFFSET; - return readl_relaxed(catalog->io->dp_controller.base + offset); + return readl_relaxed(catalog->io->dp_controller.ahb.base + offset); } static inline void dp_write_ahb(struct dp_catalog_private *catalog, u32 offset, u32 data) { - offset += MSM_DP_CONTROLLER_AHB_OFFSET; /* * To make sure phy reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - writel(data, catalog->io->dp_controller.base + offset); + writel(data, catalog->io->dp_controller.ahb.base + offset); } static inline void dp_write_p0(struct dp_catalog_private *catalog, u32 offset, u32 data) { - offset += MSM_DP_CONTROLLER_P0_OFFSET; /* * To make sure interface reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - writel(data, catalog->io->dp_controller.base + offset); + writel(data, catalog->io->dp_controller.p0.base + offset); } static inline u32 dp_read_p0(struct dp_catalog_private *catalog, u32 offset) { - offset += MSM_DP_CONTROLLER_P0_OFFSET; /* * To make sure interface reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - return readl_relaxed(catalog->io->dp_controller.base + offset); + return readl_relaxed(catalog->io->dp_controller.p0.base + offset); } static inline u32 dp_read_link(struct dp_catalog_private *catalog, u32 offset) { - offset += MSM_DP_CONTROLLER_LINK_OFFSET; - return
Re: [Freedreno] [PATCH v3 3/5] drm/msm/dp: Refactor ioremap wrapper
On 2021-10-01 10:43, Bjorn Andersson wrote: In order to deal with multiple memory ranges in the following commit change the ioremap wrapper to not poke directly into the dss_io_data struct. While at it, devm_ioremap_resource() already prints useful error messages on failure, so omit the unnecessary prints from the caller. Signed-off-by: Bjorn Andersson Reviewed-by: Abhinav Kumar --- Changes since v2: - Switched to devm_platform_get_and_ioremap_resource() drivers/gpu/drm/msm/dp/dp_parser.c | 35 ++ drivers/gpu/drm/msm/dp/dp_parser.h | 2 +- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index c064ced78278..c05ba1990218 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -19,40 +19,27 @@ static const struct dp_regulator_cfg sdm845_dp_reg_cfg = { }, }; -static int msm_dss_ioremap(struct platform_device *pdev, - struct dss_io_data *io_data) +static void __iomem *dp_ioremap(struct platform_device *pdev, int idx, size_t *len) { - struct resource *res = NULL; + struct resource *res; + void __iomem *base; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - DRM_ERROR("%pS->%s: msm_dss_get_res failed\n", - __builtin_return_address(0), __func__); - return -ENODEV; - } - - io_data->len = (u32)resource_size(res); - io_data->base = devm_ioremap(>dev, res->start, io_data->len); - if (!io_data->base) { - DRM_ERROR("%pS->%s: ioremap failed\n", - __builtin_return_address(0), __func__); - return -EIO; - } + base = devm_platform_get_and_ioremap_resource(pdev, idx, ); + if (!IS_ERR(base)) + *len = resource_size(res); - return 0; + return base; } static int dp_parser_ctrl_res(struct dp_parser *parser) { - int rc = 0; struct platform_device *pdev = parser->pdev; struct dp_io *io = >io; + struct dss_io_data *dss = >dp_controller; - rc = msm_dss_ioremap(pdev, >dp_controller); - if (rc) { - DRM_ERROR("unable to remap dp io resources, rc=%d\n", rc); - return rc; - } + dss->base = dp_ioremap(pdev, 0, >len); + if (IS_ERR(dss->base)) + return PTR_ERR(dss->base); io->phy = devm_phy_get(>dev, "dp"); if (IS_ERR(io->phy)) diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index 34b49628bbaf..dc62e70b1640 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -26,7 +26,7 @@ enum dp_pm_type { }; struct dss_io_data { - u32 len; + size_t len; void __iomem *base; };
Re: [Freedreno] [PATCH v3 1/5] dt-bindings: msm/dp: Change reg definition
On 2021-10-01 10:43, Bjorn Andersson wrote: reg was defined as one region covering the entire DP block, but the memory map is actually split in 4 regions and obviously the size of these regions differs between platforms. Switch the reg to require that all four regions are specified instead. It is expected that the implementation will handle existing DTBs, even though the schema defines the new layout. Reviewed-by: Stephen Boyd Reviewed-by: Rob Herring Signed-off-by: Bjorn Andersson Reviewed-by: Abhinav Kumar --- Changes since v2: - None .../bindings/display/msm/dp-controller.yaml | 13 +++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index d89b3c510c27..6bb424c21340 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -19,7 +19,12 @@ properties: - qcom,sc7180-dp reg: -maxItems: 1 +items: + - description: ahb register block + - description: aux register block + - description: link register block + - description: p0 register block + - description: p1 register block interrupts: maxItems: 1 @@ -99,7 +104,11 @@ examples: displayport-controller@ae9 { compatible = "qcom,sc7180-dp"; -reg = <0xae9 0x1400>; +reg = <0xae9 0x200>, + <0xae90200 0x200>, + <0xae90400 0xc00>, + <0xae91000 0x400>, + <0xae91400 0x400>; interrupt-parent = <>; interrupts = <12>; clocks = < DISP_CC_MDSS_AHB_CLK>,
Re: [Freedreno] [PATCH v3 5/5] drm/msm/dp: Add sc8180x DP controllers
On 2021-10-01 11:00, Bjorn Andersson wrote: The sc8180x has 2 DP and 1 eDP controllers, add support for these to the DP driver. Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson Reviewed-by: Abhinav Kumar --- Changes since v2: - None drivers/gpu/drm/msm/dp/dp_display.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index ff3477474c5d..56a79aeffed4 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -127,8 +127,15 @@ static const struct msm_dp_config sc7180_dp_cfg = { .num_descs = 1, }; +static const struct msm_dp_config sc8180x_dp_cfg = { + .io_start = { 0xae9, 0xae98000, 0xae9a000 }, + .num_descs = 3, +}; + static const struct of_device_id dp_dt_match[] = { { .compatible = "qcom,sc7180-dp", .data = _dp_cfg }, + { .compatible = "qcom,sc8180x-dp", .data = _dp_cfg }, + { .compatible = "qcom,sc8180x-edp", .data = _dp_cfg }, {} };
Re: [PATCH v3 4/5] dt-bindings: msm/dp: Add SC8180x compatibles
On 2021-10-01 11:00, Bjorn Andersson wrote: The Qualcomm SC8180x has 2 DP controllers and 1 eDP controller, add compatibles for these to the msm/dp binding. Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson Reviewed-by: Abhinav Kumar --- Changes since v2: - None .../devicetree/bindings/display/msm/dp-controller.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index 6bb424c21340..63e585f48789 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -17,6 +17,8 @@ properties: compatible: enum: - qcom,sc7180-dp + - qcom,sc8180x-dp + - qcom,sc8180x-edp reg: items:
Re: [Freedreno] [PATCH v3 3/5] drm/msm/dp: Support up to 3 DP controllers
On 2021-10-05 13:16, abhin...@codeaurora.org wrote: On 2021-10-01 11:00, Bjorn Andersson wrote: Based on the removal of the g_dp_display and the movement of the priv->dp lookup into the DP code it's now possible to have multiple DP instances. In line with the other controllers in the MSM driver, introduce a per-compatible list of base addresses which is used to resolve the "instance id" for the given DP controller. This instance id is used as index in the priv->dp[] array. Then extend the initialization code to initialize struct drm_encoder for each of the registered priv->dp[] and update the logic for associating each struct msm_dp with the struct dpu_encoder_virt. Lastly, bump the number of struct msm_dp instances carries by priv->dp to 3, the currently known maximum number of controllers found in a Qualcomm SoC. Signed-off-by: Bjorn Andersson --- Changes since v2: - Added MSM_DRM_DP_COUNT to link the two 3s - Moved NULL check for msm_dp_debugfs_init() to the call site - Made struct dp_display_private->id unsigned I also implemented added connector_type to each of the DP instances and propagated this to dp_drm_connector_init() but later dropped this again per Doug's suggestion that we'll base this on the presence/absence of a associated drm bridge or panel. Hi Bjorn / Doug I suggest we add the dp_drm_connector_init() part back to this change. Having the same connector type for DP and eDP is an error and instead of blocking/pending it on a potential RFC which attaches a panel to DP, I would rather do it right here. So till thats done, I would retract my R-B. Thanks Abhinav drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66 +++ .../gpu/drm/msm/disp/msm_disp_snapshot_util.c | 8 ++- drivers/gpu/drm/msm/dp/dp_display.c | 44 - drivers/gpu/drm/msm/msm_drv.h | 4 +- 5 files changed, 90 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index b7f33da2799c..9cd9539a1504 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2173,7 +2173,7 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, dpu_encoder_vsync_event_handler, 0); else if (disp_info->intf_type == DRM_MODE_ENCODER_TMDS) - dpu_enc->dp = priv->dp; + dpu_enc->dp = priv->dp[disp_info->h_tile_instance[0]]; At this point this is a nit but not sure if this is right to use the tile_instance as the index. In the future if we chose to assign another index to the h_tile_instance, this would break. But I cant think of the use-case for that yet. INIT_DELAYED_WORK(_enc->delayed_off_work, dpu_encoder_off_work); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index f655adbc2421..875b07e7183d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -188,6 +188,7 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) struct dentry *entry; struct drm_device *dev; struct msm_drm_private *priv; + int i; if (!p) return -EINVAL; @@ -203,8 +204,10 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) dpu_debugfs_vbif_init(dpu_kms, entry); dpu_debugfs_core_irq_init(dpu_kms, entry); - if (priv->dp) - msm_dp_debugfs_init(priv->dp, minor); + for (i = 0; i < ARRAY_SIZE(priv->dp); i++) { + if (priv->dp[i]) + msm_dp_debugfs_init(priv->dp[i], minor); + } return dpu_core_perf_debugfs_init(dpu_kms, entry); } @@ -544,35 +547,42 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, { struct drm_encoder *encoder = NULL; struct msm_display_info info; - int rc = 0; + int rc; + int i; - if (!priv->dp) - return rc; + for (i = 0; i < ARRAY_SIZE(priv->dp); i++) { + if (!priv->dp[i]) + continue; - encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS); - if (IS_ERR(encoder)) { - DPU_ERROR("encoder init failed for dsi display\n"); - return PTR_ERR(encoder); - } + encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS); + if (IS_ERR(encoder)) { + DPU_ERROR("encoder init failed for dsi display\n"); + return PTR_ERR(encoder); + } - memset(, 0, sizeof(info)); - rc = msm_dp_modeset_init(priv->dp, dev, encoder); - if (rc) { - DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); -
Re: [Freedreno] [PATCH v3 3/5] drm/msm/dp: Support up to 3 DP controllers
On 2021-10-01 11:00, Bjorn Andersson wrote: Based on the removal of the g_dp_display and the movement of the priv->dp lookup into the DP code it's now possible to have multiple DP instances. In line with the other controllers in the MSM driver, introduce a per-compatible list of base addresses which is used to resolve the "instance id" for the given DP controller. This instance id is used as index in the priv->dp[] array. Then extend the initialization code to initialize struct drm_encoder for each of the registered priv->dp[] and update the logic for associating each struct msm_dp with the struct dpu_encoder_virt. Lastly, bump the number of struct msm_dp instances carries by priv->dp to 3, the currently known maximum number of controllers found in a Qualcomm SoC. Signed-off-by: Bjorn Andersson --- Changes since v2: - Added MSM_DRM_DP_COUNT to link the two 3s - Moved NULL check for msm_dp_debugfs_init() to the call site - Made struct dp_display_private->id unsigned I also implemented added connector_type to each of the DP instances and propagated this to dp_drm_connector_init() but later dropped this again per Doug's suggestion that we'll base this on the presence/absence of a associated drm bridge or panel. drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66 +++ .../gpu/drm/msm/disp/msm_disp_snapshot_util.c | 8 ++- drivers/gpu/drm/msm/dp/dp_display.c | 44 - drivers/gpu/drm/msm/msm_drv.h | 4 +- 5 files changed, 90 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index b7f33da2799c..9cd9539a1504 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2173,7 +2173,7 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, dpu_encoder_vsync_event_handler, 0); else if (disp_info->intf_type == DRM_MODE_ENCODER_TMDS) - dpu_enc->dp = priv->dp; + dpu_enc->dp = priv->dp[disp_info->h_tile_instance[0]]; At this point this is a nit but not sure if this is right to use the tile_instance as the index. In the future if we chose to assign another index to the h_tile_instance, this would break. But I cant think of the use-case for that yet, Hence Reviewed-by: Abhinav Kumar INIT_DELAYED_WORK(_enc->delayed_off_work, dpu_encoder_off_work); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index f655adbc2421..875b07e7183d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -188,6 +188,7 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) struct dentry *entry; struct drm_device *dev; struct msm_drm_private *priv; + int i; if (!p) return -EINVAL; @@ -203,8 +204,10 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) dpu_debugfs_vbif_init(dpu_kms, entry); dpu_debugfs_core_irq_init(dpu_kms, entry); - if (priv->dp) - msm_dp_debugfs_init(priv->dp, minor); + for (i = 0; i < ARRAY_SIZE(priv->dp); i++) { + if (priv->dp[i]) + msm_dp_debugfs_init(priv->dp[i], minor); + } return dpu_core_perf_debugfs_init(dpu_kms, entry); } @@ -544,35 +547,42 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, { struct drm_encoder *encoder = NULL; struct msm_display_info info; - int rc = 0; + int rc; + int i; - if (!priv->dp) - return rc; + for (i = 0; i < ARRAY_SIZE(priv->dp); i++) { + if (!priv->dp[i]) + continue; - encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS); - if (IS_ERR(encoder)) { - DPU_ERROR("encoder init failed for dsi display\n"); - return PTR_ERR(encoder); - } + encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS); + if (IS_ERR(encoder)) { + DPU_ERROR("encoder init failed for dsi display\n"); + return PTR_ERR(encoder); + } - memset(, 0, sizeof(info)); - rc = msm_dp_modeset_init(priv->dp, dev, encoder); - if (rc) { - DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); - drm_encoder_cleanup(encoder); - return rc; - } + memset(, 0, sizeof(info)); + rc = msm_dp_modeset_init(priv->dp[i], dev, encoder); + if (rc) { + DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); + drm_encoder_cleanup(encoder); +
Re: [Freedreno] [PATCH v3 2/5] drm/msm/dp: Modify prototype of encoder based API
On 2021-10-01 11:00, Bjorn Andersson wrote: Functions in the DisplayPort code that relates to individual instances (encoders) are passed both the struct msm_dp and the struct drm_encoder. But in a situation where multiple DP instances would exist this means that the caller need to resolve which struct msm_dp relates to the struct drm_encoder at hand. Store a reference to the struct msm_dp associated with each dpu_encoder_virt to allow the particular instance to be associate with the encoder in the following patch. Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson Reviewed-by: Abhinav Kumar --- Changes since v2: - None drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 23 - 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 0e9d3fa1544b..b7f33da2799c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -168,6 +168,7 @@ enum dpu_enc_rc_states { * @vsync_event_work: worker to handle vsync event for autorefresh * @topology: topology of the display * @idle_timeout: idle timeout duration in milliseconds + * @dp:msm_dp pointer, for DP encoders */ struct dpu_encoder_virt { struct drm_encoder base; @@ -206,6 +207,8 @@ struct dpu_encoder_virt { struct msm_display_topology topology; u32 idle_timeout; + + struct msm_dp *dp; }; #define to_dpu_encoder_virt(x) container_of(x, struct dpu_encoder_virt, base) @@ -1000,8 +1003,8 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, trace_dpu_enc_mode_set(DRMID(drm_enc)); - if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) - msm_dp_display_mode_set(priv->dp, drm_enc, mode, adj_mode); + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) + msm_dp_display_mode_set(dpu_enc->dp, drm_enc, mode, adj_mode); list_for_each_entry(conn_iter, connector_list, head) if (conn_iter->encoder == drm_enc) @@ -1182,9 +1185,8 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) _dpu_encoder_virt_enable_helper(drm_enc); - if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) { - ret = msm_dp_display_enable(priv->dp, - drm_enc); + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) { + ret = msm_dp_display_enable(dpu_enc->dp, drm_enc); if (ret) { DPU_ERROR_ENC(dpu_enc, "dp display enable failed: %d\n", ret); @@ -1224,8 +1226,8 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) /* wait for idle */ dpu_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE); - if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) { - if (msm_dp_display_pre_disable(priv->dp, drm_enc)) + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) { + if (msm_dp_display_pre_disable(dpu_enc->dp, drm_enc)) DPU_ERROR_ENC(dpu_enc, "dp display push idle failed\n"); } @@ -1253,8 +1255,8 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n"); - if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) { - if (msm_dp_display_disable(priv->dp, drm_enc)) + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) { + if (msm_dp_display_disable(dpu_enc->dp, drm_enc)) DPU_ERROR_ENC(dpu_enc, "dp display disable failed\n"); } @@ -2170,7 +2172,8 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, timer_setup(_enc->vsync_event_timer, dpu_encoder_vsync_event_handler, 0); - + else if (disp_info->intf_type == DRM_MODE_ENCODER_TMDS) + dpu_enc->dp = priv->dp; INIT_DELAYED_WORK(_enc->delayed_off_work, dpu_encoder_off_work);
Re: [Freedreno] [PATCH v3 1/5] drm/msm/dp: Remove global g_dp_display variable
On 2021-10-01 11:00, Bjorn Andersson wrote: As the Qualcomm DisplayPort driver only supports a single instance of the driver the commonly used struct dp_display is kept in a global variable. As we introduce additional instances this obviously doesn't work. Replace this with a combination of existing references to adjacent objects and drvdata. Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson Reviewed-by: Abhinav Kumar --- Changes since v2: - None drivers/gpu/drm/msm/dp/dp_display.c | 80 - 1 file changed, 21 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index fbe4c2cd52a3..5d3ee5ef07c2 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -27,7 +27,6 @@ #include "dp_audio.h" #include "dp_debug.h" -static struct msm_dp *g_dp_display; #define HPD_STRING_SIZE 30 enum { @@ -121,6 +120,13 @@ static const struct of_device_id dp_dt_match[] = { {} }; +static struct dp_display_private *dev_get_dp_display_private(struct device *dev) +{ + struct msm_dp *dp = dev_get_drvdata(dev); + + return container_of(dp, struct dp_display_private, dp_display); +} + static int dp_add_event(struct dp_display_private *dp_priv, u32 event, u32 data, u32 delay) { @@ -197,15 +203,12 @@ static int dp_display_bind(struct device *dev, struct device *master, void *data) { int rc = 0; - struct dp_display_private *dp; - struct drm_device *drm; + struct dp_display_private *dp = dev_get_dp_display_private(dev); struct msm_drm_private *priv; + struct drm_device *drm; drm = dev_get_drvdata(master); - dp = container_of(g_dp_display, - struct dp_display_private, dp_display); - dp->dp_display.drm_dev = drm; priv = drm->dev_private; priv->dp = &(dp->dp_display); @@ -240,13 +243,10 @@ static int dp_display_bind(struct device *dev, struct device *master, static void dp_display_unbind(struct device *dev, struct device *master, void *data) { - struct dp_display_private *dp; + struct dp_display_private *dp = dev_get_dp_display_private(dev); struct drm_device *drm = dev_get_drvdata(master); struct msm_drm_private *priv = drm->dev_private; - dp = container_of(g_dp_display, - struct dp_display_private, dp_display); - dp_power_client_deinit(dp->power); dp_aux_unregister(dp->aux); priv->dp = NULL; @@ -379,38 +379,17 @@ static void dp_display_host_deinit(struct dp_display_private *dp) static int dp_display_usbpd_configure_cb(struct device *dev) { - int rc = 0; - struct dp_display_private *dp; - - if (!dev) { - DRM_ERROR("invalid dev\n"); - rc = -EINVAL; - goto end; - } - - dp = container_of(g_dp_display, - struct dp_display_private, dp_display); + struct dp_display_private *dp = dev_get_dp_display_private(dev); dp_display_host_init(dp, false); - rc = dp_display_process_hpd_high(dp); -end: - return rc; + return dp_display_process_hpd_high(dp); } static int dp_display_usbpd_disconnect_cb(struct device *dev) { int rc = 0; - struct dp_display_private *dp; - - if (!dev) { - DRM_ERROR("invalid dev\n"); - rc = -EINVAL; - return rc; - } - - dp = container_of(g_dp_display, - struct dp_display_private, dp_display); + struct dp_display_private *dp = dev_get_dp_display_private(dev); dp_add_event(dp, EV_USER_NOTIFICATION, false, 0); @@ -472,15 +451,7 @@ static int dp_display_usbpd_attention_cb(struct device *dev) { int rc = 0; u32 sink_request; - struct dp_display_private *dp; - - if (!dev) { - DRM_ERROR("invalid dev\n"); - return -EINVAL; - } - - dp = container_of(g_dp_display, - struct dp_display_private, dp_display); + struct dp_display_private *dp = dev_get_dp_display_private(dev); /* check for any test request issued by sink */ rc = dp_link_process_request(dp->link); @@ -647,7 +618,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) DRM_DEBUG_DP("hpd_state=%d\n", state); /* signal the disconnect event early to ensure proper teardown */ - dp_display_handle_plugged_change(g_dp_display, false); + dp_display_handle_plugged_change(>dp_display, false); /* enable HDP plug interrupt to prepare for next plugin */ dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK, true); @@ -842,9 +813,7 @@ static int dp_display_prepare(struct msm_dp *dp) static int
Re: [Freedreno] [PATCH v3 03/14] drm/hdcp: Update property value on content type and user changes
On 2021-10-01 08:11, Sean Paul wrote: From: Sean Paul This patch updates the connector's property value in 2 cases which were previously missed: 1- Content type changes. The value should revert back to DESIRED from ENABLED in case the driver must re-authenticate the link due to the new content type. 2- Userspace sets value to DESIRED while ENABLED. In this case, the value should be reset immediately to ENABLED since the link is actively being encrypted. To accommodate these changes, I've split up the conditionals to make things a bit more clear (as much as one can with this mess of state). Acked-by: Jani Nikula Signed-off-by: Sean Paul Reviewed-by: Abhinav Kumar Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-4-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-4-s...@poorly.run #v2 Changes in v2: -None Changes in v3: -Fixed indentation issue identified by 0-day --- drivers/gpu/drm/drm_hdcp.c | 26 +- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c index dd8fa91c51d6..8c851d40cd45 100644 --- a/drivers/gpu/drm/drm_hdcp.c +++ b/drivers/gpu/drm/drm_hdcp.c @@ -487,21 +487,29 @@ bool drm_hdcp_atomic_check(struct drm_connector *connector, return true; /* -* Nothing to do if content type is unchanged and one of: -* - state didn't change +* Content type changes require an HDCP disable/enable cycle. +*/ + if (new_conn_state->hdcp_content_type != old_conn_state->hdcp_content_type) { + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return true; + } + + /* +* Ignore meaningless state changes: * - HDCP was activated since the last commit -* - attempting to set to desired while already enabled +* - Attempting to set to desired while already enabled */ - if (old_hdcp == new_hdcp || - (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && + if ((old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { - if (old_conn_state->hdcp_content_type == - new_conn_state->hdcp_content_type) - return false; + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_ENABLED; + return false; } - return true; + /* Finally, if state changes, we need action */ + return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_atomic_check);
Re: [PATCH] drm/msm: potential error pointer dereference in init()
On 2021-10-04 03:38, Dan Carpenter wrote: The msm_iommu_new() returns error pointers on failure so check for that to avoid an Oops. Fixes: ccac7ce373c1 ("drm/msm: Refactor address space initialization") Signed-off-by: Dan Carpenter Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index ae48f41821cf..ad247c06e198 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -908,6 +908,10 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms) return 0; mmu = msm_iommu_new(dpu_kms->dev->dev, domain); + if (IS_ERR(mmu)) { + iommu_domain_free(domain); + return PTR_ERR(mmu); + } aspace = msm_gem_address_space_create(mmu, "dpu1", 0x1000, 0x1 - 0x1000);
Re: [PATCH] drm/msm/disp: fix endian bug in debugfs code
On 2021-10-04 06:47, Dan Carpenter wrote: The "vbif->features" is type unsigned long but the debugfs file is treating it as a u32 type. This will work in little endian systems, but the correct thing is to change the debugfs to use an unsigned long. Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support") Signed-off-by: Dan Carpenter Reviewed-by: Abhinav Kumar --- You might wonder why this code has so many casts. It's required because this data is const. Which is fine because the file is read only. drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c index 21d20373eb8b..e645a886e3c6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c @@ -305,8 +305,8 @@ void dpu_debugfs_vbif_init(struct dpu_kms *dpu_kms, struct dentry *debugfs_root) debugfs_vbif = debugfs_create_dir(vbif_name, entry); - debugfs_create_u32("features", 0600, debugfs_vbif, - (u32 *)>features); + debugfs_create_ulong("features", 0600, debugfs_vbif, +(unsigned long *)>features); debugfs_create_u32("xin_halt_timeout", 0400, debugfs_vbif, (u32 *)>xin_halt_timeout);
Re: [Freedreno] [PATCH v3] drm/msm/dsi: do not enable irq handler before powering up the host
On 2021-10-01 18:08, Dmitry Baryshkov wrote: The DSI host might be left in some state by the bootloader. If this state generates an IRQ, it might hang the system by holding the interrupt line before the driver sets up the DSI host to the known state. Move the request_irq into msm_dsi_host_init and pass IRQF_NO_AUTOEN to it. Call enable/disable_irq after msm_dsi_host_power_on/_off() functions, so that we can be sure that the interrupt is delivered when the host is in the known state. It is not possible to defer the interrupt enablement to a later point, because drm_panel_prepare might need to communicate with the panel over the DSI link and that requires working interrupt. Fixes: a689554ba6ed ("drm/msm: Initial add DSI connector support") Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/dsi/dsi.h | 2 ++ drivers/gpu/drm/msm/dsi/dsi_host.c| 48 +-- drivers/gpu/drm/msm/dsi/dsi_manager.c | 16 + 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index b50db91cb8a7..569c8ff062ba 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -107,6 +107,8 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, u32 dma_base, u32 len); int msm_dsi_host_enable(struct mipi_dsi_host *host); int msm_dsi_host_disable(struct mipi_dsi_host *host); +void msm_dsi_host_enable_irq(struct mipi_dsi_host *host); +void msm_dsi_host_disable_irq(struct mipi_dsi_host *host); int msm_dsi_host_power_on(struct mipi_dsi_host *host, struct msm_dsi_phy_shared_timings *phy_shared_timings, bool is_bonded_dsi, struct msm_dsi_phy *phy); diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index e269df285136..ce26eb78cb6c 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -1898,6 +1898,23 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) return ret; } + msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + if (msm_host->irq < 0) { + ret = msm_host->irq; + dev_err(>dev, "failed to get irq: %d\n", ret); + return ret; + } + + /* do not autoenable, will be enabled later */ + ret = devm_request_irq(>dev, msm_host->irq, dsi_host_irq, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN, + "dsi_isr", msm_host); + if (ret < 0) { + dev_err(>dev, "failed to request IRQ%u: %d\n", + msm_host->irq, ret); + return ret; + } + init_completion(_host->dma_comp); init_completion(_host->video_comp); mutex_init(_host->dev_mutex); @@ -1941,25 +1958,8 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; - struct platform_device *pdev = msm_host->pdev; int ret; - msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); - if (msm_host->irq < 0) { - ret = msm_host->irq; - DRM_DEV_ERROR(dev->dev, "failed to get irq: %d\n", ret); - return ret; - } - - ret = devm_request_irq(>dev, msm_host->irq, - dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - "dsi_isr", msm_host); - if (ret < 0) { - DRM_DEV_ERROR(>dev, "failed to request IRQ%u: %d\n", - msm_host->irq, ret); - return ret; - } - msm_host->dev = dev; ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); if (ret) { @@ -2315,6 +2315,20 @@ void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host, clk_req->escclk_rate = msm_host->esc_clk_rate; } +void msm_dsi_host_enable_irq(struct mipi_dsi_host *host) +{ + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + + enable_irq(msm_host->irq); +} + +void msm_dsi_host_disable_irq(struct mipi_dsi_host *host) +{ + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + + disable_irq(msm_host->irq); +} + int msm_dsi_host_enable(struct mipi_dsi_host *host) { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index c41d39f5b7cf..fb4ccffdcfe1 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -377,6 +377,14 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) } } + /* +* Enable before preparing the panel, disable after unpreparing, so +* that the panel can communicate over the DSI
Re: [Freedreno] [PATCH v2 00/22] drm/msm/dpu: switch dpu_plane to be virtual
Hi Dmitry On 2021-07-04 18:20, Dmitry Baryshkov wrote: As discussed on IRC, change dpu_plane implementation to be virtual: register unified planes and select backing SSPP block at runtime. Use msm.dpu_use_virtual_planes=1 to enable usage of virtual planes rather than statically allocated SSPPs at the plane registration. Patches 1-9 move state variables from struct dpu_plane onto the stack allocation. State should not be a part of struct dpu_plane anyway. Patches 10-18 make additional changes to plane code, reworking check, debugfs, dropping old multirec support, which results in patch 19 adding support for virtual planes per se. Patches 20-22 demonstrate my main goal behind reworking dpu_plane support. They change dpu_plane to automatically use one of SSPP block features - multirec, an ability to display two unscaled RGB rectangles using single SSPP block. This allows us to double the amount of created planes. If the user tries to enable more planes than actually supported by the underlying SSPP blocks, atomic_check code would return an error. As you can see, this patchset is not atomic, so different patches can go separately. I am half way through this series and have finished checking patches 1-12 I am okay with patches 1-4, 6-12. Its a reasonable cleanup to make the dpu_plane struct lighter. I need a little more time with the rest as I am comparing the downstream solution against yours. As you mentioned, this patchset is not atomic, hence can you break it up like -> cleanup of dpu_plane struct in one series -> removal of current multirect and current src split which will include patch 5 as well So that the first series can go through and it gives us a little more time to check the second series. Thanks Abhinav Changes since v1: - Add multirec implementation - Added msm.dpu_use_virtual_planes kernel parameter instead of using compile time switch - Changed code to always reallocate SSPPs in the CRTC atomic check to let the kernel pick up the best multirec config. This can be optimized later. - Rework RM SSPP API to always receive plane id - Removed scaler_cfg, pixel_ext and cdp_cfg from struct dpu_plane_state - Made _dpu_scaler_setup() call sspp's setup_scaler and setup_pe - Removed dpu_csc_cfg from dpu_plane The following changes since commit e88bbc91849b2bf57683119c339e52916d34433f: Revert "drm/msm/mdp5: provide dynamic bandwidth management" (2021-06-23 14:06:20 -0700) are available in the Git repository at: https://git.linaro.org/people/dmitry.baryshkov/kernel.git dpu-multirec-2 for you to fetch changes up to 19f6afd40097d4c826e56b8f4a8cbd807f7b61f6: drm/msm/dpu: add multirect support (2021-07-05 04:04:50 +0300) Dmitry Baryshkov (22): drm/msm/dpu: move LUT levels out of QOS config drm/msm/dpu: remove pipe_qos_cfg from struct dpu_plane drm/msm/dpu: drop pipe_name from struct dpu_plane drm/msm/dpu: remove stage_cfg from struct dpu_crtc drm/msm/dpu: rip out master planes support drm/msm/dpu: move dpu_hw_pipe_cfg out of struct dpu_plane drm/msm/dpu: drop scaler config from plane state drm/msm/dpu: drop dpu_csc_cfg from dpu_plane drm/msm/dpu: remove dpu_hw_pipe_cdp_cfg from dpu_plane drm/msm/dpu: don't cache pipe->cap->features in dpu_plane drm/msm/dpu: don't cache pipe->cap->sblk in dpu_plane drm/msm/dpu: rip out debugfs support from dpu_plane drm/msm/dpu: drop src_split and multirect check from dpu_crtc_atomic_check drm/msm/dpu: add list of supported formats to the DPU caps drm/msm/dpu: simplify DPU_SSPP features checks drm/msm/dpu: do not limit the zpos property drm/msm/dpu: add support for SSPP allocation to RM drm/msm/dpu: move pipe_hw to dpu_plane_state drm/msm/dpu: add support for virtualized planes drm/msm/dpu: fix smart dma support drm/msm/dpu: fix CDP setup to account for multirect index drm/msm/dpu: add multirect support drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 261 +++- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 2 - drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 20 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 20 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c| 41 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h| 52 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c| 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h| 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c| 234 --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h| 70 +- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 851 +++-- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 75 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 81 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 6 + 14 files changed, 793 insertions(+), 924 deletions(-)
Re: [Freedreno] [PATCH v2 13/13] drm/msm: Implement HDCP 1.x using the new drm HDCP helpers
On 2021-09-28 11:02, Sean Paul wrote: On Tue, Sep 21, 2021 at 07:25:41PM -0700, abhin...@codeaurora.org wrote: On 2021-09-15 13:38, Sean Paul wrote: > From: Sean Paul > > This patch adds HDCP 1.x support to msm DP connectors using the new HDCP > helpers. > > Cc: Stephen Boyd > Signed-off-by: Sean Paul > Link: > https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-15-s...@poorly.run > #v1 > > Changes in v2: > -Squash [1] into this patch with the following changes (Stephen) > -Update the sc7180 dtsi file > -Remove resource names and just use index (Stephen) > > [1] > https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-14-s...@poorly.run > --- /snip > diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile > index 904535eda0c4..98731fd262d6 100644 > --- a/drivers/gpu/drm/msm/Makefile > +++ b/drivers/gpu/drm/msm/Makefile > @@ -109,6 +109,7 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ >dp/dp_ctrl.o \ >dp/dp_display.o \ >dp/dp_drm.o \ > + dp/dp_hdcp.o \ >dp/dp_hpd.o \ >dp/dp_link.o \ >dp/dp_panel.o \ > diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c > b/drivers/gpu/drm/msm/dp/dp_debug.c > index 2f6247e80e9d..de16fca8782a 100644 > --- a/drivers/gpu/drm/msm/dp/dp_debug.c > +++ b/drivers/gpu/drm/msm/dp/dp_debug.c /snip > +static ssize_t dp_hdcp_key_write(struct file *file, const char __user > *ubuf, > + size_t len, loff_t *offp) > +{ > + char *input_buffer; > + int ret = 0; > + struct dp_debug_private *debug = file->private_data; > + struct drm_device *dev; > + > + dev = debug->drm_dev; > + > + if (len != (DRM_HDCP_KSV_LEN + DP_HDCP_NUM_KEYS * DP_HDCP_KEY_LEN)) > + return -EINVAL; > + > + if (!debug->hdcp) > + return -ENOENT; > + > + input_buffer = memdup_user_nul(ubuf, len); > + if (IS_ERR(input_buffer)) > + return PTR_ERR(input_buffer); > + > + ret = dp_hdcp_ingest_key(debug->hdcp, input_buffer, len); > + > + kfree(input_buffer); > + if (ret < 0) { > + DRM_ERROR("Could not ingest HDCP key, ret=%d\n", ret); > + return ret; > + } > + > + *offp += len; > + return len; > +} It seems like the HDCP keys written using debugfs, just for my understanding, are you storing this in some secure partition and the usermode reads from it and writes them here? We have not sorted out the userspace side of HDCP enablement yet, so it remains to be seen whether the keys will be injected via debugfs/firmware file/property. /snip > +static int dp_connector_atomic_check(struct drm_connector *connector, > + struct drm_atomic_state *state) > +{ > + struct drm_connector_state *conn_state; > + struct dp_connector_state *dp_state; > + > + conn_state = drm_atomic_get_new_connector_state(state, connector); > + dp_state = to_dp_connector_state(conn_state); > + > + dp_state->hdcp_transition = drm_hdcp_atomic_check(connector, state); I have a general question related to the transition flag and overall tying the HDCP enable and authentication to the commit. So lets say there is a case where the driver needs to disable HDCP. It could be due to link integrity failure OR some other error condition which usermode is not aware of. In that case, we will set this hdcp_transition to true but in the next commit we will actually do the authentication. What if usermode doesnt issue a new frame? This question arises because currently the link intergrity check is done using SW polling in the previous patchset. But as I had commented there, this occurs in HW for us. I dont see that isr itself in this patchset. So wanted to understand if thats part of this approach to still tie it with commit. So if we go with the HW polling based approach which is the preferred method, we need to untie this from the commit. In the case of error, the worker will detect it and try to re-authenticate. If the re-authentication is successful, userspace will continue to be unaware and everything will keep working. If re-authentication is unsuccessful, the worker will update the property value and issue a uevent to userspace. So HDCP enablement is only tied to commits when the property value is changing as a result of userspace. Regarding SW vs HW link checks, I don't think there's any difference in efficacy between them. If HW can be relied on to issue an interrupt in failure cases, a follow-up set allowing for this seems like a great idea. Thanks for the explanation. Yes, from our experience it has been pretty reliable to issue signal integrity failures. We already had the isr based approach downstream and would prefer to keep it that way based on our experience of it firing reliably. We can still keep the SW polling code but it should come into effect only if HW polling is not supported / preferred. > + > + return 0; > +} /snip > +static int dp_hdcp_load_keys(struct drm_connector *connector) > +{ > + struct dp_hdcp
Re: [Freedreno] [PATCH v2 04/13] drm/hdcp: Expand HDCP helper library for enable/disable/check
Hi Sean On 2021-09-28 10:33, Sean Paul wrote: On Tue, Sep 21, 2021 at 04:34:59PM -0700, abhin...@codeaurora.org wrote: On 2021-09-15 13:38, Sean Paul wrote: > From: Sean Paul > > This patch expands upon the HDCP helper library to manage HDCP > enable, disable, and check. > > Previous to this patch, the majority of the state management and sink > interaction is tucked inside the Intel driver with the understanding > that once a new platform supported HDCP we could make good decisions > about what should be centralized. With the addition of HDCP support > for Qualcomm, it's time to migrate the protocol-specific bits of HDCP > authentication, key exchange, and link checks to the HDCP helper. > > In terms of functionality, this migration is 1:1 with the Intel driver, > however things are laid out a bit differently than with intel_hdcp.c, > which is why this is a separate patch from the i915 transition to the > helper. On i915, the "shim" vtable is used to account for HDMI vs. DP > vs. DP-MST differences whereas the helper library uses a LUT to > account for the register offsets and a remote read function to route > the messages. On i915, storing the sink information in the source is > done inline whereas now we use the new drm_hdcp_helper_funcs vtable > to store and fetch information to/from source hw. Finally, instead of > calling enable/disable directly from the driver, we'll leave that > decision to the helper and by calling drm_hdcp_helper_atomic_commit() > from the driver. All told, this will centralize the protocol and state > handling in the helper, ensuring we collect all of our bugs^Wlogic > in one place. > > Signed-off-by: Sean Paul > Link: > https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-5-s...@poorly.run > #v1 > > Changes in v2: > -Fixed set-but-unused variable identified by 0-day > --- > drivers/gpu/drm/drm_hdcp.c | 1103 > include/drm/drm_hdcp.h | 191 +++ > 2 files changed, 1294 insertions(+) > > diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c > index 742313ce8f6f..47c6e6923a76 100644 > --- a/drivers/gpu/drm/drm_hdcp.c > +++ b/drivers/gpu/drm/drm_hdcp.c /snip > +static void drm_hdcp_helper_check_work(struct work_struct *work) > +{ > + struct drm_hdcp_helper_data *data = > container_of(to_delayed_work(work), > + struct drm_hdcp_helper_data, > + check_work); > + unsigned long check_link_interval; > + Does this SW polling for Ri' mismatch need to be done even if the HW is capable of doing it on its own? MSM HDCP 1x HW can periodically check Ri' mismatches and issue an interrupt if there is a mismatch. In that case this SW polling is not needed. So maybe check if the HW supports polling and if so skip this SW polling? One could certainly change this to be HW driven. There is also an interrupt on Intel for DP links which [re]schedules link check in the interrupt handler, something similar could be done for msm. Note that even on these Intel links which support the CP interrupt, the worker still runs on the normal cadence. I haven't considered relying solely on the interrupt since I want to be sure we didn't miss anything. Sean I think we should have the support for HW polling added. From our experience, it has been pretty reliable for us and has a pretty consistent cadence in alignment with the spec. I dont quite understand why we should have both in chipsets capable of HW polling and am bit surprised if SW polling will catch something which HW polling and the subsequent interrupt has missed. > + mutex_lock(>mutex); > + if (data->value != DRM_MODE_CONTENT_PROTECTION_ENABLED) > + goto out_data_mutex; > + > + drm_hdcp_helper_driver_lock(data); > + > + if (data->enabled_type == DRM_MODE_HDCP_CONTENT_TYPE1) { > + if (drm_hdcp_hdcp2_check_link(data)) > + goto out; > + check_link_interval = DRM_HDCP2_CHECK_PERIOD_MS; > + } else { > + if (drm_hdcp_hdcp1_check_link(data)) > + goto out; > + check_link_interval = DRM_HDCP_CHECK_PERIOD_MS; > + } > + schedule_delayed_work(>check_work, check_link_interval); > + > +out: > + drm_hdcp_helper_driver_unlock(data); > +out_data_mutex: > + mutex_unlock(>mutex); > +} /snip
Re: [Freedreno] [PATCH v2 00/13] drm/hdcp: Pull HDCP auth/exchange/check into helpers
On 2021-09-28 11:06, Sean Paul wrote: On Tue, Sep 21, 2021 at 07:30:29PM -0700, abhin...@codeaurora.org wrote: Hi Sean On 2021-09-15 13:38, Sean Paul wrote: > From: Sean Paul > > Hello again, > This is the second version of the HDCP helper patchset. See version 1 > here: https://patchwork.freedesktop.org/series/94623/ > > In this second version, I've fixed up the oopsies exposed by 0-day and > yamllint and incorporated early review feedback from the dt/dts reviews. > > Please take a look, > > Sean One question overall on the series: 1) Regarding validation, did you run any secure video to check the transitions? Yep, the transitions look good, no visual artifacts. Unplug/replug/suspend/resume all seem to be behaving as expected. 2) Is running HDCP 1x compliance also part of the validation efforts? If Qualcomm has the ability to run validation, I'd be very keen to get some help in that regard. Thanks for letting us know. To assist with (2) we will have to work with you on some logistics. Will sync up on IRC further on how to go about this. Sean Thanks Abhinav > > Sean Paul (13): > drm/hdcp: Add drm_hdcp_atomic_check() > drm/hdcp: Avoid changing crtc state in hdcp atomic check > drm/hdcp: Update property value on content type and user changes > drm/hdcp: Expand HDCP helper library for enable/disable/check > drm/i915/hdcp: Consolidate HDCP setup/state cache > drm/i915/hdcp: Retain hdcp_capable return codes > drm/i915/hdcp: Use HDCP helpers for i915 > drm/msm/dpu_kms: Re-order dpu includes > drm/msm/dpu: Remove useless checks in dpu_encoder > drm/msm/dpu: Remove encoder->enable() hack > drm/msm/dp: Re-order dp_audio_put in deinit_sub_modules > dt-bindings: msm/dp: Add bindings for HDCP registers > drm/msm: Implement HDCP 1.x using the new drm HDCP helpers > > .../bindings/display/msm/dp-controller.yaml |7 +- > arch/arm64/boot/dts/qcom/sc7180.dtsi |4 +- > drivers/gpu/drm/drm_hdcp.c| 1197 - > drivers/gpu/drm/i915/display/intel_atomic.c |7 +- > drivers/gpu/drm/i915/display/intel_ddi.c | 29 +- > .../drm/i915/display/intel_display_debugfs.c | 11 +- > .../drm/i915/display/intel_display_types.h| 58 +- > drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 345 ++--- > drivers/gpu/drm/i915/display/intel_dp_mst.c | 17 +- > drivers/gpu/drm/i915/display/intel_hdcp.c | 1011 +++--- > drivers/gpu/drm/i915/display/intel_hdcp.h | 35 +- > drivers/gpu/drm/i915/display/intel_hdmi.c | 256 ++-- > drivers/gpu/drm/msm/Makefile |1 + > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 17 +- > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 30 +- > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |2 - > drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h |4 - > drivers/gpu/drm/msm/dp/dp_debug.c | 49 +- > drivers/gpu/drm/msm/dp/dp_debug.h |6 +- > drivers/gpu/drm/msm/dp/dp_display.c | 47 +- > drivers/gpu/drm/msm/dp/dp_display.h |5 + > drivers/gpu/drm/msm/dp/dp_drm.c | 68 +- > drivers/gpu/drm/msm/dp/dp_drm.h |5 + > drivers/gpu/drm/msm/dp/dp_hdcp.c | 433 ++ > drivers/gpu/drm/msm/dp/dp_hdcp.h | 27 + > drivers/gpu/drm/msm/dp/dp_parser.c| 22 +- > drivers/gpu/drm/msm/dp/dp_parser.h|4 + > drivers/gpu/drm/msm/dp/dp_reg.h | 44 +- > drivers/gpu/drm/msm/msm_atomic.c | 15 + > include/drm/drm_hdcp.h| 194 +++ > 30 files changed, 2561 insertions(+), 1389 deletions(-) > create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c > create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h
Re: [Freedreno] [PATCH] drm/msm/dsi: do not install irq handler before power up the host
On 2021-09-27 18:29, Dmitry Baryshkov wrote: On 28/09/2021 04:19, abhin...@codeaurora.org wrote: On 2021-09-27 18:06, Dmitry Baryshkov wrote: On Tue, 28 Sept 2021 at 03:22, wrote: On 2021-09-25 12:43, Dmitry Baryshkov wrote: > On 21/09/2021 23:52, abhin...@codeaurora.org wrote: >> On 2021-09-21 10:47, Dmitry Baryshkov wrote: >>> Hi, >>> >>> On Tue, 21 Sept 2021 at 20:01, wrote: On 2021-09-21 09:22, Dmitry Baryshkov wrote: > The DSI host might be left in some state by the bootloader. If this > state generates an IRQ, it might hang the system by holding the > interrupt line before the driver sets up the DSI host to the known > state. > > Move the request/free_irq calls into msm_dsi_host_power_on/_off calls, > so that we can be sure that the interrupt is delivered when the host is > in the known state. > > Fixes: a689554ba6ed ("drm/msm: Initial add DSI connector support") > Signed-off-by: Dmitry Baryshkov This is a valid change and we have seen interrupt storms in downstream happening when like you said the bootloader leaves the DSI host in unknown state. Just one question below. > --- >Â drivers/gpu/drm/msm/dsi/dsi_host.c | 21 - >Â 1 file changed, 12 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c > b/drivers/gpu/drm/msm/dsi/dsi_host.c > index e269df285136..cd842347a6b1 100644 > --- a/drivers/gpu/drm/msm/dsi/dsi_host.c > +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c > @@ -1951,15 +1951,6 @@ int msm_dsi_host_modeset_init(struct > mipi_dsi_host *host, >Â Â return ret; >Â Â } > > - ret = devm_request_irq(>dev, msm_host->irq, > - dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, > - "dsi_isr", msm_host); > - if (ret < 0) { > - DRM_DEV_ERROR(>dev, "failed to request IRQ%u: %d\n", > - msm_host->irq, ret); > - return ret; > - } > - >Â Â msm_host->dev = dev; >Â Â ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); >Â Â if (ret) { > @@ -2413,6 +2404,16 @@ int msm_dsi_host_power_on(struct mipi_dsi_host > *host, >Â Â if (msm_host->disp_en_gpio) >Â Â gpiod_set_value(msm_host->disp_en_gpio, 1); > > + ret = devm_request_irq(_host->pdev->dev, msm_host->irq, > + dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, > + "dsi_isr", msm_host); > + if (ret < 0) { > + DRM_DEV_ERROR(_host->pdev->dev, "failed to request IRQ%u: %d\n", > + msm_host->irq, ret); > + return ret; > + } > + > + Do you want to move this to msm_dsi_host_enable()? So without the controller being enabled it is still in unknown state? >>> >>> msm_dsi_host_power_on() reconfigures the host registers, so the state >>> is known at the end of the power_on(). >>> Also do you want to do this after dsi0 and dsi1 are initialized to account for dual dsi cases? >>> >>> I don't think this should matter. The host won't generate 'extra' >>> interrupts in such case, will it? >>> >> We have seen cases where misconfiguration has caused interrupts to >> storm only >> on one DSI in some cases. So yes, I would prefer this is done after >> both are >> configured. > > I've checked. The power_on is called from dsi_mgr_bridge_pre_enable() > when both DSI hosts should be bound. DSI being bound is enough? I thought the issue we are trying to address is that we need to have called msm_dsi_host_power_on() for both the hosts so that both are put in the known state before requesting the irq. OR in other words move the irq_enable() to below location. 341 static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) 342 { 364 ret = msm_dsi_host_power_on(host, _shared_timings[id], is_bonded_dsi, msm_dsi->phy); 365 if (ret) { 366 pr_err("%s: power on host %d failed, %d\n", __func__, id, ret); 367 goto host_on_fail; 368 } 369 370 if (is_bonded_dsi && msm_dsi1) { 371 ret = msm_dsi_host_power_on(msm_dsi1->host, 372 _shared_timings[DSI_1], is_bonded_dsi, msm_dsi1->phy); 373 if (ret) { 374 pr_err("%s: power on host1 failed, %d\n", 375 __func__, ret); 376 goto host1_on_fail; 377 } 378 } < move the irq enable here > ** Ah, I see your point. What about moving to msm_dsi_host_enable() then? Yes, I had suggested this a few replies ago. But only at the dsi_msgr we know if DSI1 is also done. So
Re: [Freedreno] [PATCH] drm/msm/dsi: do not install irq handler before power up the host
On 2021-09-27 18:06, Dmitry Baryshkov wrote: On Tue, 28 Sept 2021 at 03:22, wrote: On 2021-09-25 12:43, Dmitry Baryshkov wrote: > On 21/09/2021 23:52, abhin...@codeaurora.org wrote: >> On 2021-09-21 10:47, Dmitry Baryshkov wrote: >>> Hi, >>> >>> On Tue, 21 Sept 2021 at 20:01, wrote: On 2021-09-21 09:22, Dmitry Baryshkov wrote: > The DSI host might be left in some state by the bootloader. If this > state generates an IRQ, it might hang the system by holding the > interrupt line before the driver sets up the DSI host to the known > state. > > Move the request/free_irq calls into msm_dsi_host_power_on/_off calls, > so that we can be sure that the interrupt is delivered when the host is > in the known state. > > Fixes: a689554ba6ed ("drm/msm: Initial add DSI connector support") > Signed-off-by: Dmitry Baryshkov This is a valid change and we have seen interrupt storms in downstream happening when like you said the bootloader leaves the DSI host in unknown state. Just one question below. > --- > drivers/gpu/drm/msm/dsi/dsi_host.c | 21 - > 1 file changed, 12 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c > b/drivers/gpu/drm/msm/dsi/dsi_host.c > index e269df285136..cd842347a6b1 100644 > --- a/drivers/gpu/drm/msm/dsi/dsi_host.c > +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c > @@ -1951,15 +1951,6 @@ int msm_dsi_host_modeset_init(struct > mipi_dsi_host *host, > return ret; > } > > - ret = devm_request_irq(>dev, msm_host->irq, > - dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, > - "dsi_isr", msm_host); > - if (ret < 0) { > - DRM_DEV_ERROR(>dev, "failed to request IRQ%u: %d\n", > - msm_host->irq, ret); > - return ret; > - } > - > msm_host->dev = dev; > ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); > if (ret) { > @@ -2413,6 +2404,16 @@ int msm_dsi_host_power_on(struct mipi_dsi_host > *host, > if (msm_host->disp_en_gpio) > gpiod_set_value(msm_host->disp_en_gpio, 1); > > + ret = devm_request_irq(_host->pdev->dev, msm_host->irq, > + dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, > + "dsi_isr", msm_host); > + if (ret < 0) { > + DRM_DEV_ERROR(_host->pdev->dev, "failed to request IRQ%u: %d\n", > + msm_host->irq, ret); > + return ret; > + } > + > + Do you want to move this to msm_dsi_host_enable()? So without the controller being enabled it is still in unknown state? >>> >>> msm_dsi_host_power_on() reconfigures the host registers, so the state >>> is known at the end of the power_on(). >>> Also do you want to do this after dsi0 and dsi1 are initialized to account for dual dsi cases? >>> >>> I don't think this should matter. The host won't generate 'extra' >>> interrupts in such case, will it? >>> >> We have seen cases where misconfiguration has caused interrupts to >> storm only >> on one DSI in some cases. So yes, I would prefer this is done after >> both are >> configured. > > I've checked. The power_on is called from dsi_mgr_bridge_pre_enable() > when both DSI hosts should be bound. DSI being bound is enough? I thought the issue we are trying to address is that we need to have called msm_dsi_host_power_on() for both the hosts so that both are put in the known state before requesting the irq. OR in other words move the irq_enable() to below location. 341 static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) 342 { 364 ret = msm_dsi_host_power_on(host, _shared_timings[id], is_bonded_dsi, msm_dsi->phy); 365 if (ret) { 366 pr_err("%s: power on host %d failed, %d\n", __func__, id, ret); 367 goto host_on_fail; 368 } 369 370 if (is_bonded_dsi && msm_dsi1) { 371 ret = msm_dsi_host_power_on(msm_dsi1->host, 372 _shared_timings[DSI_1], is_bonded_dsi, msm_dsi1->phy); 373 if (ret) { 374 pr_err("%s: power on host1 failed, %d\n", 375 __func__, ret); 376 goto host1_on_fail; 377 } 378 } < move the irq enable here > ** Ah, I see your point. What about moving to msm_dsi_host_enable() then? Yes, I had suggested this a few replies ago. But only at the dsi_msgr we know if DSI1 is also done. So you can do it right after it in below location? 427 if (is_dual_dsi && msm_dsi1) { 428
Re: [Freedreno] [PATCH] drm/msm/dsi: do not install irq handler before power up the host
On 2021-09-25 12:43, Dmitry Baryshkov wrote: On 21/09/2021 23:52, abhin...@codeaurora.org wrote: On 2021-09-21 10:47, Dmitry Baryshkov wrote: Hi, On Tue, 21 Sept 2021 at 20:01, wrote: On 2021-09-21 09:22, Dmitry Baryshkov wrote: > The DSI host might be left in some state by the bootloader. If this > state generates an IRQ, it might hang the system by holding the > interrupt line before the driver sets up the DSI host to the known > state. > > Move the request/free_irq calls into msm_dsi_host_power_on/_off calls, > so that we can be sure that the interrupt is delivered when the host is > in the known state. > > Fixes: a689554ba6ed ("drm/msm: Initial add DSI connector support") > Signed-off-by: Dmitry Baryshkov This is a valid change and we have seen interrupt storms in downstream happening when like you said the bootloader leaves the DSI host in unknown state. Just one question below. > --- >Â drivers/gpu/drm/msm/dsi/dsi_host.c | 21 - >Â 1 file changed, 12 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c > b/drivers/gpu/drm/msm/dsi/dsi_host.c > index e269df285136..cd842347a6b1 100644 > --- a/drivers/gpu/drm/msm/dsi/dsi_host.c > +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c > @@ -1951,15 +1951,6 @@ int msm_dsi_host_modeset_init(struct > mipi_dsi_host *host, >Â Â return ret; >Â Â } > > - ret = devm_request_irq(>dev, msm_host->irq, > - dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, > - "dsi_isr", msm_host); > - if (ret < 0) { > - DRM_DEV_ERROR(>dev, "failed to request IRQ%u: %d\n", > - msm_host->irq, ret); > - return ret; > - } > - >Â Â msm_host->dev = dev; >Â Â ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); >Â Â if (ret) { > @@ -2413,6 +2404,16 @@ int msm_dsi_host_power_on(struct mipi_dsi_host > *host, >Â Â if (msm_host->disp_en_gpio) >Â Â gpiod_set_value(msm_host->disp_en_gpio, 1); > > + ret = devm_request_irq(_host->pdev->dev, msm_host->irq, > + dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, > + "dsi_isr", msm_host); > + if (ret < 0) { > + DRM_DEV_ERROR(_host->pdev->dev, "failed to request IRQ%u: %d\n", > + msm_host->irq, ret); > + return ret; > + } > + > + Do you want to move this to msm_dsi_host_enable()? So without the controller being enabled it is still in unknown state? msm_dsi_host_power_on() reconfigures the host registers, so the state is known at the end of the power_on(). Also do you want to do this after dsi0 and dsi1 are initialized to account for dual dsi cases? I don't think this should matter. The host won't generate 'extra' interrupts in such case, will it? We have seen cases where misconfiguration has caused interrupts to storm only on one DSI in some cases. So yes, I would prefer this is done after both are configured. I've checked. The power_on is called from dsi_mgr_bridge_pre_enable() when both DSI hosts should be bound. DSI being bound is enough? I thought the issue we are trying to address is that we need to have called msm_dsi_host_power_on() for both the hosts so that both are put in the known state before requesting the irq. OR in other words move the irq_enable() to below location. 341 static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) 342 { 364 ret = msm_dsi_host_power_on(host, _shared_timings[id], is_bonded_dsi, msm_dsi->phy); 365 if (ret) { 366 pr_err("%s: power on host %d failed, %d\n", __func__, id, ret); 367 goto host_on_fail; 368 } 369 370 if (is_bonded_dsi && msm_dsi1) { 371 ret = msm_dsi_host_power_on(msm_dsi1->host, 372 _shared_timings[DSI_1], is_bonded_dsi, msm_dsi1->phy); 373 if (ret) { 374 pr_err("%s: power on host1 failed, %d\n", 375 __func__, ret); 376 goto host1_on_fail; 377 } 378 } < move the irq enable here > ** >Â Â msm_host->power_on = true; >Â Â mutex_unlock(_host->dev_mutex); > > @@ -2439,6 +2440,8 @@ int msm_dsi_host_power_off(struct mipi_dsi_host > *host) >Â Â goto unlock_ret; >Â Â } > > + devm_free_irq(_host->pdev->dev, msm_host->irq, msm_host); > + >Â Â dsi_ctrl_config(msm_host, false, NULL, NULL); > >Â Â if (msm_host->disp_en_gpio)
Re: [Freedreno] [PATCH v2 00/13] drm/hdcp: Pull HDCP auth/exchange/check into helpers
Hi Sean On 2021-09-15 13:38, Sean Paul wrote: From: Sean Paul Hello again, This is the second version of the HDCP helper patchset. See version 1 here: https://patchwork.freedesktop.org/series/94623/ In this second version, I've fixed up the oopsies exposed by 0-day and yamllint and incorporated early review feedback from the dt/dts reviews. Please take a look, Sean One question overall on the series: 1) Regarding validation, did you run any secure video to check the transitions? 2) Is running HDCP 1x compliance also part of the validation efforts? Thanks Abhinav Sean Paul (13): drm/hdcp: Add drm_hdcp_atomic_check() drm/hdcp: Avoid changing crtc state in hdcp atomic check drm/hdcp: Update property value on content type and user changes drm/hdcp: Expand HDCP helper library for enable/disable/check drm/i915/hdcp: Consolidate HDCP setup/state cache drm/i915/hdcp: Retain hdcp_capable return codes drm/i915/hdcp: Use HDCP helpers for i915 drm/msm/dpu_kms: Re-order dpu includes drm/msm/dpu: Remove useless checks in dpu_encoder drm/msm/dpu: Remove encoder->enable() hack drm/msm/dp: Re-order dp_audio_put in deinit_sub_modules dt-bindings: msm/dp: Add bindings for HDCP registers drm/msm: Implement HDCP 1.x using the new drm HDCP helpers .../bindings/display/msm/dp-controller.yaml |7 +- arch/arm64/boot/dts/qcom/sc7180.dtsi |4 +- drivers/gpu/drm/drm_hdcp.c| 1197 - drivers/gpu/drm/i915/display/intel_atomic.c |7 +- drivers/gpu/drm/i915/display/intel_ddi.c | 29 +- .../drm/i915/display/intel_display_debugfs.c | 11 +- .../drm/i915/display/intel_display_types.h| 58 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 345 ++--- drivers/gpu/drm/i915/display/intel_dp_mst.c | 17 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 1011 +++--- drivers/gpu/drm/i915/display/intel_hdcp.h | 35 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 256 ++-- drivers/gpu/drm/msm/Makefile |1 + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 17 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 30 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |2 - drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h |4 - drivers/gpu/drm/msm/dp/dp_debug.c | 49 +- drivers/gpu/drm/msm/dp/dp_debug.h |6 +- drivers/gpu/drm/msm/dp/dp_display.c | 47 +- drivers/gpu/drm/msm/dp/dp_display.h |5 + drivers/gpu/drm/msm/dp/dp_drm.c | 68 +- drivers/gpu/drm/msm/dp/dp_drm.h |5 + drivers/gpu/drm/msm/dp/dp_hdcp.c | 433 ++ drivers/gpu/drm/msm/dp/dp_hdcp.h | 27 + drivers/gpu/drm/msm/dp/dp_parser.c| 22 +- drivers/gpu/drm/msm/dp/dp_parser.h|4 + drivers/gpu/drm/msm/dp/dp_reg.h | 44 +- drivers/gpu/drm/msm/msm_atomic.c | 15 + include/drm/drm_hdcp.h| 194 +++ 30 files changed, 2561 insertions(+), 1389 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h
Re: [Freedreno] [PATCH v2 08/13] drm/msm/dpu_kms: Re-order dpu includes
On 2021-09-15 13:38, Sean Paul wrote: From: Sean Paul Make includes alphabetical in dpu_kms.c Signed-off-by: Sean Paul Reviewed-by: Abhinav Kumar Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-9-s...@poorly.run #v1 Changes in v2: -None --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index ae48f41821cf..fb0d9f781c66 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -21,14 +21,14 @@ #include "msm_gem.h" #include "disp/msm_disp_snapshot.h" -#include "dpu_kms.h" #include "dpu_core_irq.h" +#include "dpu_crtc.h" +#include "dpu_encoder.h" #include "dpu_formats.h" #include "dpu_hw_vbif.h" -#include "dpu_vbif.h" -#include "dpu_encoder.h" +#include "dpu_kms.h" #include "dpu_plane.h" -#include "dpu_crtc.h" +#include "dpu_vbif.h" #define CREATE_TRACE_POINTS #include "dpu_trace.h"
Re: [Freedreno] [PATCH v2 13/13] drm/msm: Implement HDCP 1.x using the new drm HDCP helpers
On 2021-09-15 13:38, Sean Paul wrote: From: Sean Paul This patch adds HDCP 1.x support to msm DP connectors using the new HDCP helpers. Cc: Stephen Boyd Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-15-s...@poorly.run #v1 Changes in v2: -Squash [1] into this patch with the following changes (Stephen) -Update the sc7180 dtsi file -Remove resource names and just use index (Stephen) [1] https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-14-s...@poorly.run --- arch/arm64/boot/dts/qcom/sc7180.dtsi | 4 +- drivers/gpu/drm/msm/Makefile | 1 + drivers/gpu/drm/msm/dp/dp_debug.c| 49 ++- drivers/gpu/drm/msm/dp/dp_debug.h| 6 +- drivers/gpu/drm/msm/dp/dp_display.c | 45 ++- drivers/gpu/drm/msm/dp/dp_display.h | 5 + drivers/gpu/drm/msm/dp/dp_drm.c | 68 - drivers/gpu/drm/msm/dp/dp_drm.h | 5 + drivers/gpu/drm/msm/dp/dp_hdcp.c | 433 +++ drivers/gpu/drm/msm/dp/dp_hdcp.h | 27 ++ drivers/gpu/drm/msm/dp/dp_parser.c | 22 +- drivers/gpu/drm/msm/dp/dp_parser.h | 4 + drivers/gpu/drm/msm/dp/dp_reg.h | 44 ++- drivers/gpu/drm/msm/msm_atomic.c | 15 + 14 files changed, 709 insertions(+), 19 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index c8921e2d6480..3ae6fc7a2c01 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -3088,7 +3088,9 @@ mdss_dp: displayport-controller@ae9 { compatible = "qcom,sc7180-dp"; status = "disabled"; - reg = <0 0x0ae9 0 0x1400>; + reg = <0 0x0ae9 0 0x1400>, + <0 0x0aed1000 0 0x174>, + <0 0x0aee1000 0 0x2c>; interrupt-parent = <>; interrupts = <12>; diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 904535eda0c4..98731fd262d6 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -109,6 +109,7 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_ctrl.o \ dp/dp_display.o \ dp/dp_drm.o \ + dp/dp_hdcp.o \ dp/dp_hpd.o \ dp/dp_link.o \ dp/dp_panel.o \ diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 2f6247e80e9d..de16fca8782a 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "dp_parser.h" #include "dp_catalog.h" @@ -15,6 +16,7 @@ #include "dp_ctrl.h" #include "dp_debug.h" #include "dp_display.h" +#include "dp_hdcp.h" #define DEBUG_NAME "msm_dp" @@ -24,6 +26,7 @@ struct dp_debug_private { struct dp_usbpd *usbpd; struct dp_link *link; struct dp_panel *panel; + struct dp_hdcp *hdcp; struct drm_connector **connector; struct device *dev; struct drm_device *drm_dev; @@ -349,6 +352,38 @@ static int dp_test_active_open(struct inode *inode, inode->i_private); } +static ssize_t dp_hdcp_key_write(struct file *file, const char __user *ubuf, +size_t len, loff_t *offp) +{ + char *input_buffer; + int ret = 0; + struct dp_debug_private *debug = file->private_data; + struct drm_device *dev; + + dev = debug->drm_dev; + + if (len != (DRM_HDCP_KSV_LEN + DP_HDCP_NUM_KEYS * DP_HDCP_KEY_LEN)) + return -EINVAL; + + if (!debug->hdcp) + return -ENOENT; + + input_buffer = memdup_user_nul(ubuf, len); + if (IS_ERR(input_buffer)) + return PTR_ERR(input_buffer); + + ret = dp_hdcp_ingest_key(debug->hdcp, input_buffer, len); + + kfree(input_buffer); + if (ret < 0) { + DRM_ERROR("Could not ingest HDCP key, ret=%d\n", ret); + return ret; + } + + *offp += len; + return len; +} It seems like the HDCP keys written using debugfs, just for my understanding, are you storing this in some secure partition and the usermode reads from it and writes them here? + static const struct file_operations dp_debug_fops = { .open = simple_open, .read = dp_debug_read_info, @@ -363,6 +398,12 @@ static const struct file_operations test_active_fops = { .write = dp_test_active_write }; +static const struct file_operations dp_hdcp_key_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .write = dp_hdcp_key_write, +}; + static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor) { int rc = 0; @@
Re: [Freedreno] [PATCH v2 04/13] drm/hdcp: Expand HDCP helper library for enable/disable/check
On 2021-09-15 13:38, Sean Paul wrote: From: Sean Paul This patch expands upon the HDCP helper library to manage HDCP enable, disable, and check. Previous to this patch, the majority of the state management and sink interaction is tucked inside the Intel driver with the understanding that once a new platform supported HDCP we could make good decisions about what should be centralized. With the addition of HDCP support for Qualcomm, it's time to migrate the protocol-specific bits of HDCP authentication, key exchange, and link checks to the HDCP helper. In terms of functionality, this migration is 1:1 with the Intel driver, however things are laid out a bit differently than with intel_hdcp.c, which is why this is a separate patch from the i915 transition to the helper. On i915, the "shim" vtable is used to account for HDMI vs. DP vs. DP-MST differences whereas the helper library uses a LUT to account for the register offsets and a remote read function to route the messages. On i915, storing the sink information in the source is done inline whereas now we use the new drm_hdcp_helper_funcs vtable to store and fetch information to/from source hw. Finally, instead of calling enable/disable directly from the driver, we'll leave that decision to the helper and by calling drm_hdcp_helper_atomic_commit() from the driver. All told, this will centralize the protocol and state handling in the helper, ensuring we collect all of our bugs^Wlogic in one place. Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-5-s...@poorly.run #v1 Changes in v2: -Fixed set-but-unused variable identified by 0-day --- drivers/gpu/drm/drm_hdcp.c | 1103 include/drm/drm_hdcp.h | 191 +++ 2 files changed, 1294 insertions(+) diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c index 742313ce8f6f..47c6e6923a76 100644 --- a/drivers/gpu/drm/drm_hdcp.c +++ b/drivers/gpu/drm/drm_hdcp.c @@ -6,15 +6,20 @@ * Ramalingam C */ +#include #include #include #include +#include +#include #include #include #include +#include #include #include +#include #include #include #include @@ -513,3 +518,1101 @@ bool drm_hdcp_atomic_check(struct drm_connector *connector, return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_atomic_check); + +struct drm_hdcp_helper_data { + struct mutex mutex; + struct mutex *driver_mutex; + + struct drm_connector *connector; + const struct drm_hdcp_helper_funcs *funcs; + + u64 value; + unsigned int enabled_type; + + struct delayed_work check_work; + struct work_struct prop_work; + + struct drm_dp_aux *aux; + const struct drm_hdcp_hdcp1_receiver_reg_lut *hdcp1_lut; +}; + +struct drm_hdcp_hdcp1_receiver_reg_lut { + unsigned int bksv; + unsigned int ri; + unsigned int aksv; + unsigned int an; + unsigned int ainfo; + unsigned int v[5]; + unsigned int bcaps; + unsigned int bcaps_mask_repeater_present; + unsigned int bstatus; +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_ddc_lut = { + .bksv = DRM_HDCP_DDC_BKSV, + .ri = DRM_HDCP_DDC_RI_PRIME, + .aksv = DRM_HDCP_DDC_AKSV, + .an = DRM_HDCP_DDC_AN, + .ainfo = DRM_HDCP_DDC_AINFO, + .v = { DRM_HDCP_DDC_V_PRIME(0), DRM_HDCP_DDC_V_PRIME(1), + DRM_HDCP_DDC_V_PRIME(2), DRM_HDCP_DDC_V_PRIME(3), + DRM_HDCP_DDC_V_PRIME(4) }, + .bcaps = DRM_HDCP_DDC_BCAPS, + .bcaps_mask_repeater_present = DRM_HDCP_DDC_BCAPS_REPEATER_PRESENT, + .bstatus = DRM_HDCP_DDC_BSTATUS, +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_dpcd_lut = { + .bksv = DP_AUX_HDCP_BKSV, + .ri = DP_AUX_HDCP_RI_PRIME, + .aksv = DP_AUX_HDCP_AKSV, + .an = DP_AUX_HDCP_AN, + .ainfo = DP_AUX_HDCP_AINFO, + .v = { DP_AUX_HDCP_V_PRIME(0), DP_AUX_HDCP_V_PRIME(1), + DP_AUX_HDCP_V_PRIME(2), DP_AUX_HDCP_V_PRIME(3), + DP_AUX_HDCP_V_PRIME(4) }, + .bcaps = DP_AUX_HDCP_BCAPS, + .bcaps_mask_repeater_present = DP_BCAPS_REPEATER_PRESENT, + + /* +* For some reason the HDMI and DP HDCP specs call this register + * definition by different names. In the HDMI spec, it's called BSTATUS, +* but in DP it's called BINFO. +*/ + .bstatus = DP_AUX_HDCP_BINFO, +}; + +static int drm_hdcp_remote_ddc_read(struct i2c_adapter *i2c, + unsigned int offset, u8 *value, size_t len) +{ + int ret; + u8 start = offset & 0xff; + struct i2c_msg msgs[] = { + { + .addr = DRM_HDCP_DDC_ADDR, + .flags = 0, + .len = 1, + .buf = , + }, + { + .addr = DRM_HDCP_DDC_ADDR, +
Re: [Freedreno] [PATCH] drm/msm/dsi: do not install irq handler before power up the host
On 2021-09-21 10:47, Dmitry Baryshkov wrote: Hi, On Tue, 21 Sept 2021 at 20:01, wrote: On 2021-09-21 09:22, Dmitry Baryshkov wrote: > The DSI host might be left in some state by the bootloader. If this > state generates an IRQ, it might hang the system by holding the > interrupt line before the driver sets up the DSI host to the known > state. > > Move the request/free_irq calls into msm_dsi_host_power_on/_off calls, > so that we can be sure that the interrupt is delivered when the host is > in the known state. > > Fixes: a689554ba6ed ("drm/msm: Initial add DSI connector support") > Signed-off-by: Dmitry Baryshkov This is a valid change and we have seen interrupt storms in downstream happening when like you said the bootloader leaves the DSI host in unknown state. Just one question below. > --- > drivers/gpu/drm/msm/dsi/dsi_host.c | 21 - > 1 file changed, 12 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c > b/drivers/gpu/drm/msm/dsi/dsi_host.c > index e269df285136..cd842347a6b1 100644 > --- a/drivers/gpu/drm/msm/dsi/dsi_host.c > +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c > @@ -1951,15 +1951,6 @@ int msm_dsi_host_modeset_init(struct > mipi_dsi_host *host, > return ret; > } > > - ret = devm_request_irq(>dev, msm_host->irq, > - dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, > - "dsi_isr", msm_host); > - if (ret < 0) { > - DRM_DEV_ERROR(>dev, "failed to request IRQ%u: %d\n", > - msm_host->irq, ret); > - return ret; > - } > - > msm_host->dev = dev; > ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); > if (ret) { > @@ -2413,6 +2404,16 @@ int msm_dsi_host_power_on(struct mipi_dsi_host > *host, > if (msm_host->disp_en_gpio) > gpiod_set_value(msm_host->disp_en_gpio, 1); > > + ret = devm_request_irq(_host->pdev->dev, msm_host->irq, > + dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, > + "dsi_isr", msm_host); > + if (ret < 0) { > + DRM_DEV_ERROR(_host->pdev->dev, "failed to request IRQ%u: %d\n", > + msm_host->irq, ret); > + return ret; > + } > + > + Do you want to move this to msm_dsi_host_enable()? So without the controller being enabled it is still in unknown state? msm_dsi_host_power_on() reconfigures the host registers, so the state is known at the end of the power_on(). Also do you want to do this after dsi0 and dsi1 are initialized to account for dual dsi cases? I don't think this should matter. The host won't generate 'extra' interrupts in such case, will it? We have seen cases where misconfiguration has caused interrupts to storm only on one DSI in some cases. So yes, I would prefer this is done after both are configured. > msm_host->power_on = true; > mutex_unlock(_host->dev_mutex); > > @@ -2439,6 +2440,8 @@ int msm_dsi_host_power_off(struct mipi_dsi_host > *host) > goto unlock_ret; > } > > + devm_free_irq(_host->pdev->dev, msm_host->irq, msm_host); > + > dsi_ctrl_config(msm_host, false, NULL, NULL); > > if (msm_host->disp_en_gpio)
Re: [Freedreno] [PATCH] drm/msm/dsi: do not install irq handler before power up the host
On 2021-09-21 09:22, Dmitry Baryshkov wrote: The DSI host might be left in some state by the bootloader. If this state generates an IRQ, it might hang the system by holding the interrupt line before the driver sets up the DSI host to the known state. Move the request/free_irq calls into msm_dsi_host_power_on/_off calls, so that we can be sure that the interrupt is delivered when the host is in the known state. Fixes: a689554ba6ed ("drm/msm: Initial add DSI connector support") Signed-off-by: Dmitry Baryshkov This is a valid change and we have seen interrupt storms in downstream happening when like you said the bootloader leaves the DSI host in unknown state. Just one question below. --- drivers/gpu/drm/msm/dsi/dsi_host.c | 21 - 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index e269df285136..cd842347a6b1 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -1951,15 +1951,6 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, return ret; } - ret = devm_request_irq(>dev, msm_host->irq, - dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - "dsi_isr", msm_host); - if (ret < 0) { - DRM_DEV_ERROR(>dev, "failed to request IRQ%u: %d\n", - msm_host->irq, ret); - return ret; - } - msm_host->dev = dev; ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); if (ret) { @@ -2413,6 +2404,16 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host, if (msm_host->disp_en_gpio) gpiod_set_value(msm_host->disp_en_gpio, 1); + ret = devm_request_irq(_host->pdev->dev, msm_host->irq, + dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "dsi_isr", msm_host); + if (ret < 0) { + DRM_DEV_ERROR(_host->pdev->dev, "failed to request IRQ%u: %d\n", + msm_host->irq, ret); + return ret; + } + + Do you want to move this to msm_dsi_host_enable()? So without the controller being enabled it is still in unknown state? Also do you want to do this after dsi0 and dsi1 are initialized to account for dual dsi cases? msm_host->power_on = true; mutex_unlock(_host->dev_mutex); @@ -2439,6 +2440,8 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host) goto unlock_ret; } + devm_free_irq(_host->pdev->dev, msm_host->irq, msm_host); + dsi_ctrl_config(msm_host, false, NULL, NULL); if (msm_host->disp_en_gpio)
Re: [Freedreno] [PATCH] drm/msm/dsi/phy: fix clock names in 28nm_8960 phy
On 2021-09-21 09:22, Dmitry Baryshkov wrote: The commit 9f91f22aafcd ("drm/msm/dsi: remove duplicate fields from dsi_pll_Nnm instances") mistakenly changed registered clock names. While the platform is in progress of migration to using clock properties in the dts rather than the global clock names, we should provide backwards compatibility. Thus restore registerd global clock names. Fixes: 9f91f22aafcd ("drm/msm/dsi: remove duplicate fields from dsi_pll_Nnm instances") Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c index aaa37456f4ee..71ed4aa0dc67 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c @@ -428,7 +428,7 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov bytediv->reg = pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9; snprintf(parent_name, 32, "dsi%dvco_clk", pll_28nm->phy->id); - snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->phy->id); + snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->phy->id + 1); bytediv_init.name = clk_name; bytediv_init.ops = _bytediv_ops; @@ -442,7 +442,7 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov return ret; provided_clocks[DSI_BYTE_PLL_CLK] = >hw; - snprintf(clk_name, 32, "dsi%dpll", pll_28nm->phy->id); + snprintf(clk_name, 32, "dsi%dpll", pll_28nm->phy->id + 1); /* DIV3 */ hw = devm_clk_hw_register_divider(dev, clk_name, parent_name, 0, pll_28nm->phy->pll_base +
Re: [RESEND PATCH v6 13/14] drm/atomic: Use debug category printer for atomic state printer
On 2021-07-21 10:55, Sean Paul wrote: From: Sean Paul The atomic state is printed if the DRM_UT_STATE is active, but it's printed at INFO level. This patch converts it to use the debug category printer so: a- it's consistent with other DRM_UT_STATE logging b- it's properly routed through drm_trace when introduced Signed-off-by: Sean Paul Reviewed-by: Abhinav Kumar Changes in v6: -Added to the set --- drivers/gpu/drm/drm_atomic_uapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 7e48d40600ff..7615ded60195 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -1322,7 +1322,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, struct drm_out_fence_state *fence_state; int ret = 0; unsigned int i, j, num_fences; - struct drm_printer p = drm_info_printer(dev->dev); + struct drm_printer p = drm_debug_category_printer(DRM_UT_STATE, "commit_state"); /* disallow for drivers not supporting atomic: */ if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
Re: [RESEND PATCH v6 10/14] drm/print: Add drm_debug_category_printer
On 2021-07-21 10:55, Sean Paul wrote: From: Sean Paul This patch adds a new printer which will select the appropriate output for a given debug category. Currently there is only one output target, which is syslog. However in the future we'll have tracefs and it will be useful to print to syslog, tracefs, or both. Drivers just need to create the printer for the appropriate category and the printer will decide where to send the output. Signed-off-by: Sean Paul Reviewed-by: Abhinav Kumar Link: https://patchwork.freedesktop.org/patch/msgid/20200608210505.48519-11-s...@poorly.run #v5 Changes in v5: -Added to the set Changes in v6: -None --- drivers/gpu/drm/drm_print.c | 5 + include/drm/drm_print.h | 28 2 files changed, 33 insertions(+) diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c index 2ff7a6ecc632..4d984a01b3a3 100644 --- a/drivers/gpu/drm/drm_print.c +++ b/drivers/gpu/drm/drm_print.c @@ -172,6 +172,11 @@ void __drm_printfn_err(struct drm_printer *p, struct va_format *vaf) } EXPORT_SYMBOL(__drm_printfn_err); +void __drm_printfn_noop(struct drm_printer *p, struct va_format *vaf) +{ +} +EXPORT_SYMBOL(__drm_printfn_noop); + /** * drm_puts - print a const string to a _printer stream * @p: the printer diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h index 2ea0ffd9c1ce..af31beeb82a1 100644 --- a/include/drm/drm_print.h +++ b/include/drm/drm_print.h @@ -87,6 +87,7 @@ void __drm_puts_seq_file(struct drm_printer *p, const char *str); void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf); void __drm_printfn_debug_syslog(struct drm_printer *p, struct va_format *vaf); void __drm_printfn_err(struct drm_printer *p, struct va_format *vaf); +void __drm_printfn_noop(struct drm_printer *p, struct va_format *vaf); __printf(2, 3) void drm_printf(struct drm_printer *p, const char *f, ...); @@ -329,6 +330,33 @@ static inline bool drm_debug_enabled(enum drm_debug_category category) return drm_debug_syslog_enabled(category); } +/** + * drm_debug_category_printer - construct a _printer that outputs to + * pr_debug() if enabled for the given category. + * @category: the DRM_UT_* message category this message belongs to + * @prefix: trace output prefix + * + * RETURNS: + * The _printer object + */ +static inline struct drm_printer +drm_debug_category_printer(enum drm_debug_category category, + const char *prefix) +{ + struct drm_printer p = { + .prefix = prefix + }; + + if (drm_debug_syslog_enabled(category)) { + p.printfn = __drm_printfn_debug_syslog; + } else { + WARN(1, "Debug category %d is inactive.", category); + p.printfn = __drm_printfn_noop; + } + + return p; +} + /* * struct device based logging *
Re: [RESEND PATCH v6 05/14] drm/print: rename drm_debug* to be more syslog-centric
On 2021-07-21 10:55, Sean Paul wrote: From: Sean Paul In preparation for tracefs support, rename drm_debug related functions to reflect that it targets the syslog. This will allow us to selectively target syslog and/or tracefs. No functional changes here. Signed-off-by: Sean Paul Reviewed-by: Abhinav Kumar Link: https://patchwork.freedesktop.org/patch/msgid/20200608210505.48519-6-s...@poorly.run #v5 Changes in v5: -Added to the set Changes in v6: -None --- drivers/gpu/drm/drm_print.c | 12 ++-- include/drm/drm_print.h | 13 + 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c index 111b932cf2a9..2ff7a6ecc632 100644 --- a/drivers/gpu/drm/drm_print.c +++ b/drivers/gpu/drm/drm_print.c @@ -37,11 +37,11 @@ #include /* - * __drm_debug: Enable debug output. + * __drm_debug_syslog: Enable debug output to system logs * Bitmask of DRM_UT_x. See include/drm/drm_print.h for details. */ -unsigned int __drm_debug; -EXPORT_SYMBOL(__drm_debug); +unsigned int __drm_debug_syslog; +EXPORT_SYMBOL(__drm_debug_syslog); MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug category.\n" "\t\tBit 0 (0x01) will enable CORE messages (drm core code)\n" @@ -52,7 +52,7 @@ MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug cat "\t\tBit 5 (0x20) will enable VBL messages (vblank code)\n" "\t\tBit 7 (0x80) will enable LEASE messages (leasing code)\n" "\t\tBit 8 (0x100) will enable DP messages (displayport code)"); -module_param_named(debug, __drm_debug, int, 0600); +module_param_named(debug, __drm_debug_syslog, int, 0600); void __drm_puts_coredump(struct drm_printer *p, const char *str) { @@ -160,11 +160,11 @@ void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf) } EXPORT_SYMBOL(__drm_printfn_info); -void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf) +void __drm_printfn_debug_syslog(struct drm_printer *p, struct va_format *vaf) { pr_debug("%s %pV", p->prefix, vaf); } -EXPORT_SYMBOL(__drm_printfn_debug); +EXPORT_SYMBOL(__drm_printfn_debug_syslog); void __drm_printfn_err(struct drm_printer *p, struct va_format *vaf) { diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h index 9b66be54dd16..2ea0ffd9c1ce 100644 --- a/include/drm/drm_print.h +++ b/include/drm/drm_print.h @@ -35,7 +35,7 @@ #include /* Do *not* use outside of drm_print.[ch]! */ -extern unsigned int __drm_debug; +extern unsigned int __drm_debug_syslog; /** * DOC: print @@ -85,7 +85,7 @@ void __drm_puts_coredump(struct drm_printer *p, const char *str); void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf); void __drm_puts_seq_file(struct drm_printer *p, const char *str); void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf); -void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf); +void __drm_printfn_debug_syslog(struct drm_printer *p, struct va_format *vaf); void __drm_printfn_err(struct drm_printer *p, struct va_format *vaf); __printf(2, 3) @@ -227,7 +227,7 @@ static inline struct drm_printer drm_info_printer(struct device *dev) static inline struct drm_printer drm_debug_printer(const char *prefix) { struct drm_printer p = { - .printfn = __drm_printfn_debug, + .printfn = __drm_printfn_debug_syslog, .prefix = prefix }; return p; @@ -319,9 +319,14 @@ enum drm_debug_category { DRM_UT_DRMRES = 0x200, }; +static inline bool drm_debug_syslog_enabled(enum drm_debug_category category) +{ + return unlikely(__drm_debug_syslog & category); +} + static inline bool drm_debug_enabled(enum drm_debug_category category) { - return unlikely(__drm_debug & category); + return drm_debug_syslog_enabled(category); } /*
Re: [RESEND PATCH v6 05/14] drm/print: rename drm_debug* to be more syslog-centric
On 2021-07-21 10:55, Sean Paul wrote: From: Sean Paul In preparation for tracefs support, rename drm_debug related functions to reflect that it targets the syslog. This will allow us to selectively target syslog and/or tracefs. No functional changes here. Signed-off-by: Sean Paul Reviewed-by: Abhinav Kumar Link: https://patchwork.freedesktop.org/patch/msgid/20200608210505.48519-6-s...@poorly.run #v5 Changes in v5: -Added to the set Changes in v6: -None --- drivers/gpu/drm/drm_print.c | 12 ++-- include/drm/drm_print.h | 13 + 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c index 111b932cf2a9..2ff7a6ecc632 100644 --- a/drivers/gpu/drm/drm_print.c +++ b/drivers/gpu/drm/drm_print.c @@ -37,11 +37,11 @@ #include /* - * __drm_debug: Enable debug output. + * __drm_debug_syslog: Enable debug output to system logs * Bitmask of DRM_UT_x. See include/drm/drm_print.h for details. */ -unsigned int __drm_debug; -EXPORT_SYMBOL(__drm_debug); +unsigned int __drm_debug_syslog; +EXPORT_SYMBOL(__drm_debug_syslog); MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug category.\n" "\t\tBit 0 (0x01) will enable CORE messages (drm core code)\n" @@ -52,7 +52,7 @@ MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug cat "\t\tBit 5 (0x20) will enable VBL messages (vblank code)\n" "\t\tBit 7 (0x80) will enable LEASE messages (leasing code)\n" "\t\tBit 8 (0x100) will enable DP messages (displayport code)"); -module_param_named(debug, __drm_debug, int, 0600); +module_param_named(debug, __drm_debug_syslog, int, 0600); void __drm_puts_coredump(struct drm_printer *p, const char *str) { @@ -160,11 +160,11 @@ void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf) } EXPORT_SYMBOL(__drm_printfn_info); -void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf) +void __drm_printfn_debug_syslog(struct drm_printer *p, struct va_format *vaf) { pr_debug("%s %pV", p->prefix, vaf); } -EXPORT_SYMBOL(__drm_printfn_debug); +EXPORT_SYMBOL(__drm_printfn_debug_syslog); void __drm_printfn_err(struct drm_printer *p, struct va_format *vaf) { diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h index 9b66be54dd16..2ea0ffd9c1ce 100644 --- a/include/drm/drm_print.h +++ b/include/drm/drm_print.h @@ -35,7 +35,7 @@ #include /* Do *not* use outside of drm_print.[ch]! */ -extern unsigned int __drm_debug; +extern unsigned int __drm_debug_syslog; /** * DOC: print @@ -85,7 +85,7 @@ void __drm_puts_coredump(struct drm_printer *p, const char *str); void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf); void __drm_puts_seq_file(struct drm_printer *p, const char *str); void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf); -void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf); +void __drm_printfn_debug_syslog(struct drm_printer *p, struct va_format *vaf); void __drm_printfn_err(struct drm_printer *p, struct va_format *vaf); __printf(2, 3) @@ -227,7 +227,7 @@ static inline struct drm_printer drm_info_printer(struct device *dev) static inline struct drm_printer drm_debug_printer(const char *prefix) { struct drm_printer p = { - .printfn = __drm_printfn_debug, + .printfn = __drm_printfn_debug_syslog, .prefix = prefix }; return p; @@ -319,9 +319,14 @@ enum drm_debug_category { DRM_UT_DRMRES = 0x200, }; +static inline bool drm_debug_syslog_enabled(enum drm_debug_category category) +{ + return unlikely(__drm_debug_syslog & category); +} + static inline bool drm_debug_enabled(enum drm_debug_category category) { - return unlikely(__drm_debug & category); + return drm_debug_syslog_enabled(category); } /*
Re: [Freedreno] [RESEND PATCH v6 04/14] drm/msm/dpu: Replace definitions for dpu debug macros
On 2021-07-21 10:55, Sean Paul wrote: From: Sean Paul The debug messages shouldn't be logged as errors when debug categories are enabled. Use the drm logging helpers to do the right thing Signed-off-by: Sean Paul Reviewed-by: Abhinav Kumar Link: https://patchwork.freedesktop.org/patch/msgid/20200608210505.48519-5-s...@poorly.run #v5 Changes in v5: -Added to the set Changes in v6: -None --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 20 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 323a6bce9e64..c33164d3944a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -31,27 +31,15 @@ * DPU_DEBUG - macro for kms/plane/crtc/encoder/connector logs * @fmt: Pointer to format string */ -#define DPU_DEBUG(fmt, ...) \ - do { \ - if (drm_debug_enabled(DRM_UT_KMS)) \ - DRM_DEBUG(fmt, ##__VA_ARGS__); \ - else \ - pr_debug(fmt, ##__VA_ARGS__); \ - } while (0) +#define DPU_DEBUG(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__) /** * DPU_DEBUG_DRIVER - macro for hardware driver logging * @fmt: Pointer to format string */ -#define DPU_DEBUG_DRIVER(fmt, ...) \ - do { \ - if (drm_debug_enabled(DRM_UT_DRIVER)) \ - DRM_ERROR(fmt, ##__VA_ARGS__); \ - else \ - pr_debug(fmt, ##__VA_ARGS__); \ - } while (0) - -#define DPU_ERROR(fmt, ...) pr_err("[dpu error]" fmt, ##__VA_ARGS__) +#define DPU_DEBUG_DRIVER(fmt, ...) DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__) + +#define DPU_ERROR(fmt, ...) DRM_ERROR(fmt, ##__VA_ARGS__) /** * ktime_compare_safe - compare two ktime structures
Re: [RESEND PATCH v6 14/14] drm/print: Add tracefs support to the drm logging helpers
On 2021-07-21 10:55, Sean Paul wrote: From: Sean Paul This patch adds a new module parameter called drm.trace which accepts the same mask as drm.debug. When a debug category is enabled, log messages will be put in a new tracefs instance called drm for consumption. Using the new tracefs instance will allow distros to enable drm logging in production without impacting performance or spamming the system logs. Cc: Daniel Vetter Cc: David Airlie Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Pekka Paalanen Cc: Rob Clark Cc: Steven Rostedt Cc: Thomas Zimmermann Cc: Ville Syrjälä Cc: Chris Wilson Cc: Steven Rostedt Reported-by: kernel test robot # warning reported in v6 Acked-by: Pekka Paalanen Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20191010204823.195540-1-s...@poorly.run #v1 Link: https://lists.freedesktop.org/archives/dri-devel/2019-November/243230.html #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20191212203301.142437-1-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200114172155.215463-1-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200608210505.48519-14-s...@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200818210510.49730-15-s...@poorly.run #v6 Changes in v5: -Re-write to use trace_array and the tracefs instance support Changes in v6: -Use the new trace_array_init_printk() to initialize global trace buffers Changes in v6.5: -Fix kernel test robot warning -Add a trace printf in __drm_err --- Documentation/gpu/drm-uapi.rst | 6 + drivers/gpu/drm/drm_drv.c | 3 + drivers/gpu/drm/drm_print.c| 223 - include/drm/drm_print.h| 63 -- 4 files changed, 255 insertions(+), 40 deletions(-) diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 7e51dd40bf6e..ce1ea39fb4b9 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -424,6 +424,12 @@ Debugfs Support .. kernel-doc:: drivers/gpu/drm/drm_debugfs.c :export: +DRM Tracing +--- + +.. kernel-doc:: drivers/gpu/drm/drm_print.c + :doc: DRM Tracing + Sysfs Support = diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 8804ec7d3215..71dc0b161b51 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -1034,12 +1034,15 @@ static void drm_core_exit(void) drm_sysfs_destroy(); idr_destroy(_minors_idr); drm_connector_ida_destroy(); + drm_trace_cleanup(); } static int __init drm_core_init(void) { int ret; + drm_trace_init(); Can we move the drm_trace_init() to drm_dev_register()? The reason is while creating the tracefs node, I think its useful to have the drm device id to support multiple DRM devices. So while creating the tracefs node, we can do something like trace_array_get_by_name("drm_ + drm_connector_ida_init(); idr_init(_minors_idr); drm_memcpy_init_early(); diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c index 4d984a01b3a3..64d9a724c2df 100644 --- a/drivers/gpu/drm/drm_print.c +++ b/drivers/gpu/drm/drm_print.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -43,17 +44,34 @@ unsigned int __drm_debug_syslog; EXPORT_SYMBOL(__drm_debug_syslog); -MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug category.\n" -"\t\tBit 0 (0x01) will enable CORE messages (drm core code)\n" -"\t\tBit 1 (0x02) will enable DRIVER messages (drm controller code)\n" -"\t\tBit 2 (0x04) will enable KMS messages (modesetting code)\n" -"\t\tBit 3 (0x08) will enable PRIME messages (prime code)\n" -"\t\tBit 4 (0x10) will enable ATOMIC messages (atomic code)\n" -"\t\tBit 5 (0x20) will enable VBL messages (vblank code)\n" -"\t\tBit 7 (0x80) will enable LEASE messages (leasing code)\n" -"\t\tBit 8 (0x100) will enable DP messages (displayport code)"); +/* + * __drm_debug_trace: Enable debug output in drm tracing instance. + * Bitmask of DRM_UT_x. See include/drm/drm_print.h for details. + */ +unsigned int __drm_debug_trace; +EXPORT_SYMBOL(__drm_debug_trace); + +#define DEBUG_PARM_DESC(dst) \ +"Enable debug output to " dst ", where each bit enables a debug category.\n" \ +"\t\tBit 0 (0x01) will enable CORE messages (drm core code)\n" \ +"\t\tBit 1 (0x02) will enable DRIVER messages (drm controller code)\n" \ +"\t\tBit 2 (0x04) will enable KMS messages (modesetting code)\n" \ +"\t\tBit 3 (0x08) will enable PRIME messages (prime code)\n" \ +"\t\tBit 4 (0x10) will enable ATOMIC messages (atomic code)\n" \ +"\t\tBit 5 (0x20) will enable VBL messages (vblank code)\n" \ +"\t\tBit 7 (0x80) will enable LEASE messages (leasing code)\n" \ +"\t\tBit 8 (0x100) will enable DP messages (displayport code)" This is certainly a great start. Moving forward a bit, is there a possibility to subcatergorize
Re: [RESEND PATCH v6 00/14] drm/trace: Mirror DRM debug logs to tracefs
On 2021-07-21 10:55, Sean Paul wrote: From: Sean Paul Hi all, I just had the pleasure of rebasing this set on our CrOS downstream kernel and wanted to resend it for consideration once again. There hasn't been any resistence to the set AFAIK, just perhaps not enough motivation for anyone to hit the go bit. There was some interest from the msm folks about a month ago, and it has been an invaluable tool on CrOS for the past ~year. Hopefully someone can dig into this and provide some feedback so we can move this forward. Thanks! Sean Totally agree, This tool has been valuable for us in debugging many issues. FWIW, I will go through the core bits and msm pieces to give my RB. Changes since last v6: -Rebased on drm-tip Original v6 of the set available here: https://patchwork.freedesktop.org/series/78133/ https://lore.kernel.org/dri-devel/20200818210510.49730-1-s...@poorly.run/ Sean Paul (14): drm/mipi_dbi: Convert pr_debug calls to DRM_DEBUG_DRIVER drm/sil164: Convert dev_printk to drm_dev_dbg drm/i915/utils: Replace dev_printk with drm helpers drm/msm/dpu: Replace definitions for dpu debug macros drm/print: rename drm_debug* to be more syslog-centric drm/amd: Gate i2c transaction logs on drm_debug_syslog drm/etnaviv: Change buffer dump checks to target syslog drm/nouveau: Change debug checks to specifically target syslog drm/i915: Change infoframe debug checks to specify syslog drm/print: Add drm_debug_category_printer drm/mst: Convert debug printers to debug category printers drm/i915: Use debug category printer for welcome message drm/atomic: Use debug category printer for atomic state printer drm/print: Add tracefs support to the drm logging helpers Documentation/gpu/drm-uapi.rst | 6 + drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c | 4 +- drivers/gpu/drm/drm_atomic_uapi.c| 2 +- drivers/gpu/drm/drm_dp_mst_topology.c| 9 +- drivers/gpu/drm/drm_drv.c| 3 + drivers/gpu/drm/drm_mipi_dbi.c | 8 +- drivers/gpu/drm/drm_print.c | 242 --- drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 8 +- drivers/gpu/drm/i2c/sil164_drv.c | 12 +- drivers/gpu/drm/i915/display/intel_display.c | 4 +- drivers/gpu/drm/i915/i915_drv.c | 3 +- drivers/gpu/drm/i915/i915_utils.c| 5 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 20 +- drivers/gpu/drm/nouveau/nouveau_drv.h| 4 +- include/drm/drm_print.h | 96 +++- 15 files changed, 331 insertions(+), 95 deletions(-)
Re: [Freedreno] [PATCH] drm/msm: Do not run snapshot on non-DPU devices
Hi Fabio Ah, I did not realize that amd compatible is present in the list and its quite a surprise. /* * We don't know what's the best binding to link the gpu with the drm device. * Fow now, we just hunt for all the possible gpus that we support, and add them * as components. */ static const struct of_device_id msm_gpu_match[] = { { .compatible = "qcom,adreno" }, { .compatible = "qcom,adreno-3xx" }, { .compatible = "amd,imageon" }, { .compatible = "qcom,kgsl-3d0" }, { }, }; https://github.com/torvalds/linux/commit/e6f6d63ed14c20528aa6df05a8f0707c183c6ba3 For this change itself, Reviewed-by: Abhinav Kumar On 2021-09-16 09:24, Fabio Estevam wrote: Hi Abhinav, On Thu, Sep 16, 2021 at 1:15 PM wrote: Hi Fabio Thanks for confirming. Although I have no issues with your change, I am curious why even msm is probing and/or binding. Your device tree should not be having any mdp/dpu nodes then. The i.MX53 does have the following GPU node: compatible = "amd,imageon-200.0", "amd,imageon"; That's why it probes the msm driver. However, i.MX53 does not have any of the Qualcomm display controllers. It uses the i.MX IPU display controller instead. Hope that clarifies. Please reply with a Reviewed-by if you are happy with my fix. Thanks
Re: [Freedreno] [PATCH] drm/msm: Do not run snapshot on non-DPU devices
Hi Fabio Thanks for confirming. Although I have no issues with your change, I am curious why even msm is probing and/or binding. Your device tree should not be having any mdp/dpu nodes then. Thanks Abhinav On 2021-09-16 04:42, Fabio Estevam wrote: Hi Abhinav, On Wed, Sep 15, 2021 at 11:22 PM wrote: Are you not using DPU or are you not using mdp4/mdp5 as well? Even if you are using any of mdps, kms should not be NULL. Hence wanted to check the test case. I am running i.MX53, which is an NXP SoC, not Qualcomm's. It does not use DPU, nor MDP4/5 and kms is NULL in this case. Some debug prints to confirm: --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -557,18 +557,22 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) case KMS_MDP4: kms = mdp4_kms_init(ddev); priv->kms = kms; + pr_err(" KMS_MDP4\n"); break; case KMS_MDP5: kms = mdp5_kms_init(ddev); + pr_err(" KMS_MDP5\n"); break; case KMS_DPU: kms = dpu_kms_init(ddev); + pr_err(" KMS_DPU\n"); priv->kms = kms; break; default: /* valid only for the dummy headless case, where of_node=NULL */ WARN_ON(dev->of_node); kms = NULL; + pr_err(" KMS is NULL\n"); break; } # dmesg | grep KMS [3.153215] KMS is NULL
Re: [Freedreno] [PATCH] drm/msm: Do not run snapshot on non-DPU devices
Hi Fabio On 2021-09-14 10:48, Fabio Estevam wrote: Since commit 98659487b845 ("drm/msm: add support to take dpu snapshot") the following NULL pointer dereference is seen on i.MX53: [ 3.275493] msm msm: bound 3000.gpu (ops a3xx_ops) [ 3.287174] [drm] Initialized msm 1.8.0 20130625 for msm on minor 0 [ 3.293915] 8<--- cut here --- [ 3.297012] Unable to handle kernel NULL pointer dereference at virtual address 0028 [ 3.305244] pgd = (ptrval) [ 3.307989] [0028] *pgd= [ 3.311624] Internal error: Oops: 805 [#1] SMP ARM [ 3.316430] Modules linked in: [ 3.319503] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.14.0+g682d702b426b #1 [ 3.326652] Hardware name: Freescale i.MX53 (Device Tree Support) [ 3.332754] PC is at __mutex_init+0x14/0x54 [ 3.336969] LR is at msm_disp_snapshot_init+0x24/0xa0 i.MX53 does not use the DPU controller. Fix the problem by only calling msm_disp_snapshot_init() on platforms that use the DPU controller. Cc: sta...@vger.kernel.org Fixes: 98659487b845 ("drm/msm: add support to take dpu snapshot") Signed-off-by: Fabio Estevam --- drivers/gpu/drm/msm/msm_drv.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 2e6fc185e54d..2aa2266454b7 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -630,10 +630,11 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) if (ret) goto err_msm_uninit; - ret = msm_disp_snapshot_init(ddev); - if (ret) - DRM_DEV_ERROR(dev, "msm_disp_snapshot_init failed ret = %d\n", ret); - + if (kms) { + ret = msm_disp_snapshot_init(ddev); + if (ret) + DRM_DEV_ERROR(dev, "msm_disp_snapshot_init failed ret = %d\n", ret); + } Are you not using DPU or are you not using mdp4/mdp5 as well? Even if you are using any of mdps, kms should not be NULL. Hence wanted to check the test case. drm_mode_config_reset(ddev); #ifdef CONFIG_DRM_FBDEV_EMULATION
Re: [PATCH] drm/msm/dsi: Use division result from div_u64_rem in 7nm and 14nm PLL
On 2021-09-06 13:25, Marijn Suijten wrote: div_u64_rem provides the result of the divison and additonally the remainder; don't use this function to solely calculate the remainder while calculating the division again with div_u64. A similar improvement was applied earlier to the 10nm pll in 5c191fef4ce2 ("drm/msm/dsi_pll_10nm: Fix dividing the same numbers twice"). Signed-off-by: Marijn Suijten Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 4 +--- drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c index 3c1e2106d962..8905f365c932 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c @@ -213,9 +213,7 @@ static void pll_14nm_dec_frac_calc(struct dsi_pll_14nm *pll, struct dsi_pll_conf DBG("vco_clk_rate=%lld ref_clk_rate=%lld", vco_clk_rate, fref); dec_start_multiple = div_u64(vco_clk_rate * multiplier, fref); - div_u64_rem(dec_start_multiple, multiplier, _frac_start); - - dec_start = div_u64(dec_start_multiple, multiplier); + dec_start = div_u64_rem(dec_start_multiple, multiplier, _frac_start); pconf->dec_start = (u32)dec_start; pconf->div_frac_start = div_frac_start; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c index c77c30628cca..1a5abbd9fb76 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -114,9 +114,7 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll, struct dsi_pll_config multiplier = 1 << FRAC_BITS; dec_multiple = div_u64(pll_freq * multiplier, divider); - div_u64_rem(dec_multiple, multiplier, ); - - dec = div_u64(dec_multiple, multiplier); + dec = div_u64_rem(dec_multiple, multiplier, ); if (!(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1)) config->pll_clock_inverters = 0x28;
Re: [Freedreno] [PATCH v2 7/7] drm/msm/dpu: remove struct dpu_encoder_irq and enum dpu_intr_idx
On 2021-06-17 15:20, Dmitry Baryshkov wrote: Drop the wrapping structures and the enum used to index those structures in dpu_kms. Instead of them use IRQ indices and callback functions directly. Signed-off-by: Dmitry Baryshkov Is this change really needed because I think the enum based approach is good. Even in the diff stats, the LOC reduced is not that significant. Having one dpu_encoder_irq struct with the information contained seems reasonable to me. Can you please explain any redundancy or benefits of this approach that i am missing? --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 47 +- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 48 +++--- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 94 +++ .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 53 --- drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 12 +-- 5 files changed, 92 insertions(+), 162 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 3d8864df8605..55ae3ede5846 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -241,11 +241,11 @@ static void _dpu_encoder_setup_dither(struct dpu_hw_pingpong *hw_pp, unsigned bp } void dpu_encoder_helper_report_irq_timeout(struct dpu_encoder_phys *phys_enc, - enum dpu_intr_idx intr_idx) + int irq_idx) { DRM_ERROR("irq timeout id=%u, intf=%d, pp=%d, intr=%d\n", DRMID(phys_enc->parent), phys_enc->intf_idx - INTF_0, - phys_enc->hw_pp->idx - PINGPONG_0, intr_idx); + phys_enc->hw_pp->idx - PINGPONG_0, irq_idx); if (phys_enc->parent_ops->handle_frame_done) phys_enc->parent_ops->handle_frame_done( @@ -257,75 +257,70 @@ static int dpu_encoder_helper_wait_event_timeout(int32_t drm_id, u32 irq_idx, struct dpu_encoder_wait_info *info); int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, - enum dpu_intr_idx intr_idx, + int irq_idx, void (*irq_cb)(void *, int), struct dpu_encoder_wait_info *wait_info) { - struct dpu_encoder_irq *irq; u32 irq_status; int ret; - if (!wait_info || intr_idx >= INTR_IDX_MAX) { + if (!wait_info || irq_idx < 0) { DPU_ERROR("invalid params\n"); return -EINVAL; } - irq = _enc->irq[intr_idx]; /* note: do master / slave checking outside */ /* return EWOULDBLOCK since we know the wait isn't necessary */ if (phys_enc->enable_state == DPU_ENC_DISABLED) { - DRM_ERROR("encoder is disabled id=%u, intr=%d, irq=%d", - DRMID(phys_enc->parent), intr_idx, - irq->irq_idx); + DRM_ERROR("encoder is disabled id=%u, irq=%d", + DRMID(phys_enc->parent), irq_idx); return -EWOULDBLOCK; } - if (irq->irq_idx < 0) { - DRM_DEBUG_KMS("skip irq wait id=%u, intr=%d, irq=%s", - DRMID(phys_enc->parent), intr_idx, - irq->name); + if (irq_idx < 0) { + DRM_DEBUG_KMS("skip irq wait id=%u", DRMID(phys_enc->parent)); return 0; } - DRM_DEBUG_KMS("id=%u, intr=%d, irq=%d, pp=%d, pending_cnt=%d", - DRMID(phys_enc->parent), intr_idx, - irq->irq_idx, phys_enc->hw_pp->idx - PINGPONG_0, + DRM_DEBUG_KMS("id=%u, irq=%d, pp=%d, pending_cnt=%d", + DRMID(phys_enc->parent), + irq_idx, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); ret = dpu_encoder_helper_wait_event_timeout( DRMID(phys_enc->parent), - irq->irq_idx, + irq_idx, wait_info); if (ret <= 0) { irq_status = dpu_core_irq_read(phys_enc->dpu_kms, - irq->irq_idx, true); + irq_idx, true); if (irq_status) { unsigned long flags; - DRM_DEBUG_KMS("irq not triggered id=%u, intr=%d, " + DRM_DEBUG_KMS("irq not triggered id=%u, " "irq=%d, pp=%d, atomic_cnt=%d", - DRMID(phys_enc->parent), intr_idx, - irq->irq_idx, + DRMID(phys_enc->parent), + irq_idx, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); local_irq_save(flags); - irq->func(phys_enc,
Re: [Freedreno] [PATCH v2 6/7] drm/msm/dpu: get rid of dpu_encoder_helper_(un)register_irq
On 2021-06-17 15:20, Dmitry Baryshkov wrote: Get rid of dpu_encoder_helper_register_irq/unregister_irq helpers, call dpu_core_register/unregister_callback directly, without surrounding them with helpers. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 64 --- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 18 -- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 39 +++ .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 21 -- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 4 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 29 +++-- 6 files changed, 56 insertions(+), 119 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index d3557b0f4db9..3d8864df8605 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -333,70 +333,6 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, return ret; } -int dpu_encoder_helper_register_irq(struct dpu_encoder_phys *phys_enc, - enum dpu_intr_idx intr_idx) -{ - struct dpu_encoder_irq *irq; - int ret = 0; - - if (intr_idx >= INTR_IDX_MAX) { - DPU_ERROR("invalid params\n"); - return -EINVAL; - } - irq = _enc->irq[intr_idx]; - - if (irq->irq_idx < 0) { - DPU_ERROR_PHYS(phys_enc, - "invalid IRQ index:%d\n", irq->irq_idx); - return -EINVAL; - } - - ret = dpu_core_irq_register_callback(phys_enc->dpu_kms, irq->irq_idx, - irq->func, phys_enc); - if (ret) { - DPU_ERROR_PHYS(phys_enc, - "failed to register IRQ callback for %s\n", - irq->name); - irq->irq_idx = -EINVAL; - return ret; - } - - trace_dpu_enc_irq_register_success(DRMID(phys_enc->parent), intr_idx, - irq->irq_idx); - - return ret; -} - -int dpu_encoder_helper_unregister_irq(struct dpu_encoder_phys *phys_enc, - enum dpu_intr_idx intr_idx) -{ - struct dpu_encoder_irq *irq; - int ret; - - irq = _enc->irq[intr_idx]; - - /* silently skip irqs that weren't registered */ - if (irq->irq_idx < 0) { - DRM_ERROR("duplicate unregister id=%u, intr=%d, irq=%d", - DRMID(phys_enc->parent), intr_idx, - irq->irq_idx); - return 0; - } - - ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, irq->irq_idx, - irq->func, phys_enc); - if (ret) { - DRM_ERROR("unreg cb fail id=%u, intr=%d, irq=%d ret=%d", - DRMID(phys_enc->parent), intr_idx, - irq->irq_idx, ret); - } - - trace_dpu_enc_irq_unregister_success(DRMID(phys_enc->parent), intr_idx, -irq->irq_idx); - - return 0; -} - int dpu_encoder_get_frame_count(struct drm_encoder *drm_enc) { struct dpu_encoder_virt *dpu_enc; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index 80d87871fd94..ff2218155b44 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -364,22 +364,4 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, enum dpu_intr_idx intr_idx, struct dpu_encoder_wait_info *wait_info); -/** - * dpu_encoder_helper_register_irq - register and enable an irq - * @phys_enc: Pointer to physical encoder structure - * @intr_idx: encoder interrupt index - * @Return: 0 or -ERROR - */ -int dpu_encoder_helper_register_irq(struct dpu_encoder_phys *phys_enc, - enum dpu_intr_idx intr_idx); - -/** - * dpu_encoder_helper_unregister_irq - unregister and disable an irq - * @phys_enc: Pointer to physical encoder structure - * @intr_idx: encoder interrupt index - * @Return: 0 or -ERROR - */ -int dpu_encoder_helper_unregister_irq(struct dpu_encoder_phys *phys_enc, - enum dpu_intr_idx intr_idx); - #endif /* __dpu_encoder_phys_H__ */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c index f921a5c99456..4bfeac821f51 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c @@ -211,7 +211,9 @@ static int _dpu_encoder_phys_cmd_handle_ppdone_timeout( cmd_enc->pp_timeout_report_cnt, atomic_read(_enc->pending_kickoff_cnt)); msm_disp_snapshot_state(drm_enc->dev); - dpu_encoder_helper_unregister_irq(phys_enc, INTR_IDX_RDPTR); +
Re: [Freedreno] [PATCH v2 5/7] drm/msm/dpu: remove extra wrappers around dpu_core_irq
On 2021-06-17 15:20, Dmitry Baryshkov wrote: Remove extra dpu_irq_* wrappers from dpu_kms.c, merge them directly into dpu_core_irq_* functions. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h | 12 - .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 9 --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 27 +++ 3 files changed, 15 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h index 44ab97fb2964..afc8cd546368 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h @@ -10,24 +10,24 @@ /** * dpu_core_irq_preinstall - perform pre-installation of core IRQ handler - * @dpu_kms: DPU handle + * @kms: MSM KMS handle * @return:none */ -void dpu_core_irq_preinstall(struct dpu_kms *dpu_kms); +void dpu_core_irq_preinstall(struct msm_kms *kms); /** * dpu_core_irq_uninstall - uninstall core IRQ handler - * @dpu_kms: DPU handle + * @kms: MSM KMS handle * @return:none */ -void dpu_core_irq_uninstall(struct dpu_kms *dpu_kms); +void dpu_core_irq_uninstall(struct msm_kms *kms); /** * dpu_core_irq - core IRQ handler - * @dpu_kms: DPU handle + * @kms: MSM KMS handle * @return:interrupt handling status */ -irqreturn_t dpu_core_irq(struct dpu_kms *dpu_kms); +irqreturn_t dpu_core_irq(struct msm_kms *kms); /** * dpu_core_irq_read - IRQ helper function for reading IRQ status diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index 7062e7f0e860..9b74cfdf5355 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -140,8 +140,9 @@ static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, int irq_idx) dpu_kms->hw_intr->irq_tbl[irq_idx].cb(dpu_kms->hw_intr->irq_tbl[irq_idx].arg, irq_idx); } -irqreturn_t dpu_core_irq(struct dpu_kms *dpu_kms) +irqreturn_t dpu_core_irq(struct msm_kms *kms) { + struct dpu_kms *dpu_kms = to_dpu_kms(kms); struct dpu_hw_intr *intr = dpu_kms->hw_intr; int reg_idx; int irq_idx; @@ -526,8 +527,9 @@ void dpu_debugfs_core_irq_init(struct dpu_kms *dpu_kms, } #endif -void dpu_core_irq_preinstall(struct dpu_kms *dpu_kms) +void dpu_core_irq_preinstall(struct msm_kms *kms) { + struct dpu_kms *dpu_kms = to_dpu_kms(kms); int i; pm_runtime_get_sync(_kms->pdev->dev); @@ -539,8 +541,9 @@ void dpu_core_irq_preinstall(struct dpu_kms *dpu_kms) atomic_set(_kms->hw_intr->irq_tbl[i].count, 0); } -void dpu_core_irq_uninstall(struct dpu_kms *dpu_kms) +void dpu_core_irq_uninstall(struct msm_kms *kms) { + struct dpu_kms *dpu_kms = to_dpu_kms(kms); int i; pm_runtime_get_sync(_kms->pdev->dev); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 1d3a4f395e74..c1706205a514 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -761,20 +761,6 @@ static void _dpu_kms_set_encoder_mode(struct msm_kms *kms, encoder->base.id, rc); } -static irqreturn_t dpu_irq(struct msm_kms *kms) -{ - struct dpu_kms *dpu_kms = to_dpu_kms(kms); - - return dpu_core_irq(dpu_kms); -} - -static void dpu_irq_preinstall(struct msm_kms *kms) -{ - struct dpu_kms *dpu_kms = to_dpu_kms(kms); - - dpu_core_irq_preinstall(dpu_kms); -} - static int dpu_irq_postinstall(struct msm_kms *kms) { struct msm_drm_private *priv; @@ -792,13 +778,6 @@ static int dpu_irq_postinstall(struct msm_kms *kms) return 0; } -static void dpu_irq_uninstall(struct msm_kms *kms) -{ - struct dpu_kms *dpu_kms = to_dpu_kms(kms); - - dpu_core_irq_uninstall(dpu_kms); -} - static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_kms *kms) { int i; @@ -846,10 +825,10 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k static const struct msm_kms_funcs kms_funcs = { .hw_init = dpu_kms_hw_init, - .irq_preinstall = dpu_irq_preinstall, + .irq_preinstall = dpu_core_irq_preinstall, .irq_postinstall = dpu_irq_postinstall, - .irq_uninstall = dpu_irq_uninstall, - .irq = dpu_irq, + .irq_uninstall = dpu_core_irq_uninstall, + .irq = dpu_core_irq, .enable_commit = dpu_kms_enable_commit, .disable_commit = dpu_kms_disable_commit, .vsync_time = dpu_kms_vsync_time,
Re: [Freedreno] [PATCH v2 4/7] drm/msm/dpu: allow just single IRQ callback
On 2021-06-17 15:20, Dmitry Baryshkov wrote: DPU interrupts code allows multiple callbacks per interrut. In reality /interrupt none of the interrupts is shared between blocks (and will probably never be). Drop support for registering multiple callbacks per interrupt to simplify interrupt handling code. Signed-off-by: Dmitry Baryshkov I need to check on why we had this design originally and we still do. the idx with which we are registering today can generate only one hw interrupt. But i am not sure if something for planned for future use. Will update in a day or two. meanwhile some comments and questions below. --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h | 18 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 6 +- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 2 +- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 10 +- .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 6 +- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 144 +++--- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 12 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 12 -- drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 10 +- 9 files changed, 86 insertions(+), 134 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h index 90ae6c9ccc95..44ab97fb2964 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h @@ -46,10 +46,8 @@ u32 dpu_core_irq_read( * interrupt * @dpu_kms: DPU handle * @irq_idx: irq index - * @irq_cb:IRQ callback structure, containing callback function - * and argument. Passing NULL for irq_cb will unregister - * the callback for the given irq_idx - * This must exist until un-registration. + * @irq_cb:IRQ callback funcion. + * @irq_arg: IRQ callback argument. * @return:0 for success registering callback, otherwise failure * * This function supports registration of multiple callbacks for each interrupt. @@ -57,17 +55,16 @@ u32 dpu_core_irq_read( int dpu_core_irq_register_callback( struct dpu_kms *dpu_kms, int irq_idx, - struct dpu_irq_callback *irq_cb); + void (*irq_cb)(void *arg, int irq_idx), + void *irq_arg); /** * dpu_core_irq_unregister_callback - For unregistering callback function on IRQ * interrupt * @dpu_kms: DPU handle * @irq_idx: irq index - * @irq_cb:IRQ callback structure, containing callback function - * and argument. Passing NULL for irq_cb will unregister - * the callback for the given irq_idx - * This must match with registration. + * @irq_cb:IRQ callback funcion. /function this typo is there in multiple places + * @irq_arg: IRQ callback argument. * @return:0 for success registering callback, otherwise failure * * This function supports registration of multiple callbacks for each interrupt. @@ -75,7 +72,8 @@ int dpu_core_irq_register_callback( int dpu_core_irq_unregister_callback( struct dpu_kms *dpu_kms, int irq_idx, - struct dpu_irq_callback *irq_cb); + void (*irq_cb)(void *arg, int irq_idx), + void *irq_arg); /** * dpu_debugfs_core_irq_init - register core irq debugfs diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 1c04b7cce43e..d3557b0f4db9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -310,7 +310,7 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); local_irq_save(flags); - irq->cb.func(phys_enc, irq->irq_idx); + irq->func(phys_enc, irq->irq_idx); local_irq_restore(flags); ret = 0; } else { @@ -352,7 +352,7 @@ int dpu_encoder_helper_register_irq(struct dpu_encoder_phys *phys_enc, } ret = dpu_core_irq_register_callback(phys_enc->dpu_kms, irq->irq_idx, - >cb); + irq->func, phys_enc); if (ret) { DPU_ERROR_PHYS(phys_enc, "failed to register IRQ callback for %s\n", @@ -384,7 +384,7 @@ int dpu_encoder_helper_unregister_irq(struct dpu_encoder_phys *phys_enc, } ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, irq->irq_idx, - >cb); + irq->func, phys_enc); if (ret) {
Re: [Freedreno] [PATCH v2 3/7] drm/msm/dpu: merge struct dpu_irq into struct dpu_hw_intr
On 2021-06-17 15:20, Dmitry Baryshkov wrote: As dpu_core_irq was merged into dpu_hw_intr, merge data structures too, removing the need for a separate data structure. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 51 +-- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 5 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 13 - 3 files changed, 28 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index 28e9b0d448db..d2b6dca487e3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -127,20 +127,19 @@ static const struct dpu_intr_reg dpu_intr_set[] = { */ static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, int irq_idx) { - struct dpu_irq *irq_obj = _kms->irq_obj; struct dpu_irq_callback *cb; VERB("irq_idx=%d\n", irq_idx); - if (list_empty(_obj->irq_cb_tbl[irq_idx])) + if (list_empty(_kms->hw_intr->irq_cb_tbl[irq_idx])) DRM_ERROR("no registered cb, idx:%d\n", irq_idx); - atomic_inc(_obj->irq_counts[irq_idx]); + atomic_inc(_kms->hw_intr->irq_counts[irq_idx]); /* * Perform registered function callback */ - list_for_each_entry(cb, _obj->irq_cb_tbl[irq_idx], list) + list_for_each_entry(cb, _kms->hw_intr->irq_cb_tbl[irq_idx], list) if (cb->func) cb->func(cb->arg, irq_idx); } @@ -420,6 +419,10 @@ void dpu_hw_intr_destroy(struct dpu_hw_intr *intr) { if (intr) { kfree(intr->cache_irq_mask); + + kfree(intr->irq_cb_tbl); + kfree(intr->irq_counts); + kfree(intr); } } @@ -429,7 +432,7 @@ int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx, { unsigned long irq_flags; - if (!dpu_kms->irq_obj.irq_cb_tbl) { + if (!dpu_kms->hw_intr->irq_cb_tbl) { DPU_ERROR("invalid params\n"); return -EINVAL; } @@ -453,9 +456,9 @@ int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx, trace_dpu_core_irq_register_callback(irq_idx, register_irq_cb); list_del_init(_irq_cb->list); list_add_tail(_irq_cb->list, - _kms->irq_obj.irq_cb_tbl[irq_idx]); + _kms->hw_intr->irq_cb_tbl[irq_idx]); if (list_is_first(_irq_cb->list, - _kms->irq_obj.irq_cb_tbl[irq_idx])) { + _kms->hw_intr->irq_cb_tbl[irq_idx])) { int ret = dpu_hw_intr_enable_irq_locked( dpu_kms->hw_intr, irq_idx); @@ -473,7 +476,7 @@ int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx, { unsigned long irq_flags; - if (!dpu_kms->irq_obj.irq_cb_tbl) { + if (!dpu_kms->hw_intr->irq_cb_tbl) { DPU_ERROR("invalid params\n"); return -EINVAL; } @@ -497,7 +500,7 @@ int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx, trace_dpu_core_irq_unregister_callback(irq_idx, register_irq_cb); list_del_init(_irq_cb->list); /* empty callback list but interrupt is still enabled */ - if (list_empty(_kms->irq_obj.irq_cb_tbl[irq_idx])) { + if (list_empty(_kms->hw_intr->irq_cb_tbl[irq_idx])) { int ret = dpu_hw_intr_disable_irq_locked( dpu_kms->hw_intr, irq_idx); @@ -515,19 +518,18 @@ int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx, static int dpu_debugfs_core_irq_show(struct seq_file *s, void *v) { struct dpu_kms *dpu_kms = s->private; - struct dpu_irq *irq_obj = _kms->irq_obj; struct dpu_irq_callback *cb; unsigned long irq_flags; int i, irq_count, cb_count; - if (WARN_ON(!irq_obj->irq_cb_tbl)) + if (WARN_ON(!dpu_kms->hw_intr->irq_cb_tbl)) return 0; - for (i = 0; i < irq_obj->total_irqs; i++) { + for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++) { spin_lock_irqsave(_kms->hw_intr->irq_lock, irq_flags); cb_count = 0; - irq_count = atomic_read(_obj->irq_counts[i]); - list_for_each_entry(cb, _obj->irq_cb_tbl[i], list) + irq_count = atomic_read(_kms->hw_intr->irq_counts[i]); + list_for_each_entry(cb, _kms->hw_intr->irq_cb_tbl[i], list) cb_count++; spin_unlock_irqrestore(_kms->hw_intr->irq_lock, irq_flags); @@ -559,14 +561,13 @@ void dpu_core_irq_preinstall(struct dpu_kms *dpu_kms) pm_runtime_put_sync(_kms->pdev->dev); /* Create irq callbacks for all possible irq_idx */
Re: [Freedreno] [PATCH v2 2/7] drm/msm/dpu: don't clear IRQ register twice
On 2021-06-17 15:20, Dmitry Baryshkov wrote: We already clear the IRQ status register before processing IRQs, so do not clear the register again. Especially do not clear the IRQ status _after_ processing the IRQ as this way we can loose the event. Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 17 - 1 file changed, 17 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index 2437b0c7c073..28e9b0d448db 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -120,21 +120,6 @@ static const struct dpu_intr_reg dpu_intr_set[] = { #define DPU_IRQ_REG(irq_idx) (irq_idx / 32) #define DPU_IRQ_MASK(irq_idx) (BIT(irq_idx % 32)) -static void dpu_hw_intr_clear_intr_status_nolock(struct dpu_hw_intr *intr, - int irq_idx) -{ - int reg_idx; - - if (!intr) - return; - - reg_idx = DPU_IRQ_REG(irq_idx); - DPU_REG_WRITE(>hw, dpu_intr_set[reg_idx].clr_off, DPU_IRQ_MASK(irq_idx)); - - /* ensure register writes go through */ - wmb(); -} - /** * dpu_core_irq_callback_handler - dispatch core interrupts * @arg: private data of callback handler @@ -203,8 +188,6 @@ irqreturn_t dpu_core_irq(struct dpu_kms *dpu_kms) dpu_core_irq_callback_handler(dpu_kms, irq_idx); - dpu_hw_intr_clear_intr_status_nolock(intr, irq_idx); - /* * When callback finish, clear the irq_status * with the matching mask. Once irq_status
Re: [Freedreno] [PATCH v2 1/7] drm/msm/dpu: squash dpu_core_irq into dpu_hw_interrupts
On 2021-06-17 15:20, Dmitry Baryshkov wrote: With dpu_core_irq being the wrapper around dpu_hw_interrupts, there is little sense in having them separate. Squash them together to remove another layer of abstraction (hw_intr ops). Signed-off-by: Dmitry Baryshkov Overall, I think this is a reasonable cleanup, Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/Makefile | 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c | 256 - .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 269 ++ .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 87 -- 4 files changed, 214 insertions(+), 399 deletions(-) delete mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 2c00aa70b708..a5245e8d0f14 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -51,7 +51,6 @@ msm-y := \ disp/mdp5/mdp5_mixer.o \ disp/mdp5/mdp5_plane.o \ disp/mdp5/mdp5_smp.o \ - disp/dpu1/dpu_core_irq.o \ disp/dpu1/dpu_core_perf.o \ disp/dpu1/dpu_crtc.o \ disp/dpu1/dpu_encoder.o \ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c deleted file mode 100644 index d2457490930b.. --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c +++ /dev/null @@ -1,256 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt)"[drm:%s:%d] " fmt, __func__, __LINE__ - -#include -#include -#include -#include - -#include "dpu_core_irq.h" -#include "dpu_trace.h" - -/** - * dpu_core_irq_callback_handler - dispatch core interrupts - * @arg: private data of callback handler - * @irq_idx: interrupt index - */ -static void dpu_core_irq_callback_handler(void *arg, int irq_idx) -{ - struct dpu_kms *dpu_kms = arg; - struct dpu_irq *irq_obj = _kms->irq_obj; - struct dpu_irq_callback *cb; - - VERB("irq_idx=%d\n", irq_idx); - - if (list_empty(_obj->irq_cb_tbl[irq_idx])) - DRM_ERROR("no registered cb, idx:%d\n", irq_idx); - - atomic_inc(_obj->irq_counts[irq_idx]); - - /* -* Perform registered function callback -*/ - list_for_each_entry(cb, _obj->irq_cb_tbl[irq_idx], list) - if (cb->func) - cb->func(cb->arg, irq_idx); -} - -u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx, bool clear) -{ - if (!dpu_kms->hw_intr || - !dpu_kms->hw_intr->ops.get_interrupt_status) - return 0; - - if (irq_idx < 0) { - DPU_ERROR("[%pS] invalid irq_idx=%d\n", - __builtin_return_address(0), irq_idx); - return 0; - } - - return dpu_kms->hw_intr->ops.get_interrupt_status(dpu_kms->hw_intr, - irq_idx, clear); -} - -int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx, - struct dpu_irq_callback *register_irq_cb) -{ - unsigned long irq_flags; - - if (!dpu_kms->irq_obj.irq_cb_tbl) { - DPU_ERROR("invalid params\n"); - return -EINVAL; - } - - if (!register_irq_cb || !register_irq_cb->func) { - DPU_ERROR("invalid irq_cb:%d func:%d\n", - register_irq_cb != NULL, - register_irq_cb ? - register_irq_cb->func != NULL : -1); - return -EINVAL; - } - - if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) { - DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx); - return -EINVAL; - } - - VERB("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx); - - irq_flags = dpu_kms->hw_intr->ops.lock(dpu_kms->hw_intr); - trace_dpu_core_irq_register_callback(irq_idx, register_irq_cb); - list_del_init(_irq_cb->list); - list_add_tail(_irq_cb->list, - _kms->irq_obj.irq_cb_tbl[irq_idx]); - if (list_is_first(_irq_cb->list, - _kms->irq_obj.irq_cb_tbl[irq_idx])) { - int ret = dpu_kms->hw_intr->ops.enable_irq_locked( - dpu_kms->hw_intr, - irq_idx); - if (ret) - DPU_ERROR("Fail to enable IRQ for irq_idx:%d\n", - irq_idx); - } - dpu_kms->hw_intr->ops.unlock(dpu_kms->hw_intr, irq_flags); - - return 0; -} - -int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx, - struct dpu_irq_callback *register_irq_cb) -{ - unsigned long irq_flags; - - if (!dpu_kms->irq_obj.irq_cb_tbl) { - DPU_ERROR("invalid params\n"); - return
Re: [Freedreno] [PATCH] drm/msm/dpu: add support for alpha blending properties
On 2021-06-28 12:19, Dmitry Baryshkov wrote: Add support for alpha blending properties. Setup the plane blend state according to those properties. Signed-off-by: Dmitry Baryshkov I think this has already been picked up by Rob but just had a couple of comments below. Also, how has this been validated? On RB boards i dont think all the paths get executed. --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 43 --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 10 -- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 9a5c70c87cc8..768012243b44 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -30,12 +30,6 @@ #include "dpu_core_perf.h" #include "dpu_trace.h" -#define DPU_DRM_BLEND_OP_NOT_DEFINED0 -#define DPU_DRM_BLEND_OP_OPAQUE 1 -#define DPU_DRM_BLEND_OP_PREMULTIPLIED 2 -#define DPU_DRM_BLEND_OP_COVERAGE 3 -#define DPU_DRM_BLEND_OP_MAX4 - /* layer mixer index on dpu_crtc */ #define LEFT_MIXER 0 #define RIGHT_MIXER 1 @@ -146,20 +140,43 @@ static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer *mixer, { struct dpu_hw_mixer *lm = mixer->hw_lm; uint32_t blend_op; + uint32_t fg_alpha, bg_alpha; - /* default to opaque blending */ - blend_op = DPU_BLEND_FG_ALPHA_FG_CONST | - DPU_BLEND_BG_ALPHA_BG_CONST; + fg_alpha = pstate->base.alpha >> 8; + bg_alpha = 0xff - fg_alpha; - if (format->alpha_enable) { + /* default to opaque blending */ + if (pstate->base.pixel_blend_mode == DRM_MODE_BLEND_PIXEL_NONE || + !format->alpha_enable) { + blend_op = DPU_BLEND_FG_ALPHA_FG_CONST | + DPU_BLEND_BG_ALPHA_BG_CONST; + } else if (pstate->base.pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) { + blend_op = DPU_BLEND_FG_ALPHA_FG_CONST | + DPU_BLEND_BG_ALPHA_FG_PIXEL; + if (fg_alpha != 0xff) { + bg_alpha = fg_alpha; + blend_op |= DPU_BLEND_BG_MOD_ALPHA | + DPU_BLEND_BG_INV_MOD_ALPHA; + } else { + blend_op |= DPU_BLEND_BG_INV_ALPHA; + } + } else { /* coverage blending */ blend_op = DPU_BLEND_FG_ALPHA_FG_PIXEL | - DPU_BLEND_BG_ALPHA_FG_PIXEL | - DPU_BLEND_BG_INV_ALPHA; + DPU_BLEND_BG_ALPHA_FG_PIXEL; + if (fg_alpha != 0xff) { + bg_alpha = fg_alpha; + blend_op |= DPU_BLEND_FG_MOD_ALPHA | + DPU_BLEND_FG_INV_MOD_ALPHA | comparing this with the blend rule downstream, is this inversion necessary? I only see below rule downstream: 628 if (fg_alpha != 0xff) { 629 bg_alpha = fg_alpha; 630 blend_op |= SDE_BLEND_FG_MOD_ALPHA | 631 SDE_BLEND_BG_MOD_ALPHA | 632 SDE_BLEND_BG_INV_MOD_ALPHA; + DPU_BLEND_BG_MOD_ALPHA | + DPU_BLEND_BG_INV_MOD_ALPHA; + } else { + blend_op |= DPU_BLEND_BG_INV_ALPHA; + } } lm->ops.setup_blend_config(lm, pstate->stage, - 0xFF, 0, blend_op); + fg_alpha, bg_alpha, blend_op); DRM_DEBUG_ATOMIC("format:%p4cc, alpha_en:%u blend_op:0x%x\n", >base.pixel_format, format->alpha_enable, blend_op); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index ec4a6f04394a..c989621209aa 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -1339,9 +1339,7 @@ static void dpu_plane_reset(struct drm_plane *plane) return; } - pstate->base.plane = plane; - - plane->state = >base; + __drm_atomic_helper_plane_reset(plane, >base); } #ifdef CONFIG_DEBUG_FS @@ -1647,6 +1645,12 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, if (ret) DPU_ERROR("failed to install zpos property, rc = %d\n", ret); + drm_plane_create_alpha_property(plane); + drm_plane_create_blend_mode_property(plane, + BIT(DRM_MODE_BLEND_PIXEL_NONE) | + BIT(DRM_MODE_BLEND_PREMULTI) | + BIT(DRM_MODE_BLEND_COVERAGE)); + drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0, DRM_MODE_ROTATE_0 |
Re: [PATCH v5] drm/msm/dsi: add continuous clock support for 7nm PHY
On 2021-08-05 10:08, Dmitry Baryshkov wrote: Unlike previous generations, 7nm PHYs are required to collaborate with the host for conitnuos clock mode. Add changes neccessary to enable /continuous /necessary continuous clock mode in the 7nm DSI PHYs. Signed-off-by: Dmitry Baryshkov --- Changes since v4: - Fix the comment regarding msm_dsi_phy_set_continuous_clock() Changes since v3: - Invert the DSI_LANE_CTRL_HS_REQ_SEL_PHY bit logic, as noted by Abhinav. Changes since v2: - Really drop msm_dsi_phy_needs_hs_phy_sel() Changes since v1: - Remove the need for a separate msm_dsi_phy_needs_hs_phy_sel() call - Fix setting continuous clock for a dual DSI case. --- drivers/gpu/drm/msm/dsi/dsi.h | 3 ++- drivers/gpu/drm/msm/dsi/dsi.xml.h | 1 + drivers/gpu/drm/msm/dsi/dsi_host.c| 12 drivers/gpu/drm/msm/dsi/dsi_manager.c | 4 ++-- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 9 + drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 1 + drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 17 + 7 files changed, 40 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 9b8e9b07eced..58e63bf34fe9 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -109,7 +109,7 @@ int msm_dsi_host_enable(struct mipi_dsi_host *host); int msm_dsi_host_disable(struct mipi_dsi_host *host); int msm_dsi_host_power_on(struct mipi_dsi_host *host, struct msm_dsi_phy_shared_timings *phy_shared_timings, - bool is_dual_dsi); + bool is_dual_dsi, struct msm_dsi_phy *phy); int msm_dsi_host_power_off(struct mipi_dsi_host *host); int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host, const struct drm_display_mode *mode); @@ -175,6 +175,7 @@ int msm_dsi_phy_get_clk_provider(struct msm_dsi_phy *phy, void msm_dsi_phy_pll_save_state(struct msm_dsi_phy *phy); int msm_dsi_phy_pll_restore_state(struct msm_dsi_phy *phy); void msm_dsi_phy_snapshot(struct msm_disp_state *disp_state, struct msm_dsi_phy *phy); +bool msm_dsi_phy_set_continuous_clock(struct msm_dsi_phy *phy, bool enable); #endif /* __DSI_CONNECTOR_H__ */ diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h index eadbcc78fd72..473c81605054 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.xml.h +++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h @@ -518,6 +518,7 @@ static inline uint32_t DSI_CLKOUT_TIMING_CTRL_T_CLK_POST(uint32_t val) #define DSI_LANE_STATUS_DLN0_DIRECTION 0x0001 #define REG_DSI_LANE_CTRL 0x00a8 +#define DSI_LANE_CTRL_HS_REQ_SEL_PHY 0x0100 #define DSI_LANE_CTRL_CLKLN_HS_FORCE_REQUEST 0x1000 #define REG_DSI_LANE_SWAP_CTRL 0x00ac diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index ed504fe5074f..3558e5cd400f 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -834,7 +834,7 @@ static inline enum dsi_cmd_dst_format dsi_get_cmd_fmt( } static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, - struct msm_dsi_phy_shared_timings *phy_shared_timings) + struct msm_dsi_phy_shared_timings *phy_shared_timings, struct msm_dsi_phy *phy) { u32 flags = msm_host->mode_flags; enum mipi_dsi_pixel_format mipi_fmt = msm_host->format; @@ -929,6 +929,10 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, if (!(flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)) { lane_ctrl = dsi_read(msm_host, REG_DSI_LANE_CTRL); + + if (msm_dsi_phy_set_continuous_clock(phy, enable)) + lane_ctrl &= ~DSI_LANE_CTRL_HS_REQ_SEL_PHY; + dsi_write(msm_host, REG_DSI_LANE_CTRL, lane_ctrl | DSI_LANE_CTRL_CLKLN_HS_FORCE_REQUEST); } While checking downstream code and the HPG, the sequence seems to be to program ctrl bits first and then the PHY bits. Here its reverse. I think it should still work but to maintain consistency, can we change the order here to program controller first and then call msm_dsi_phy_set_continuous_clock? Unrelated to this change itself but while reviewing the sequence, I just observed we never clear the continuous clk bits during disable(). In other words the disable sequence just clears the controller and comes out. As a follow up, I will plan to clean up this a bit. @@ -2354,7 +2358,7 @@ static void msm_dsi_sfpb_config(struct msm_dsi_host *msm_host, bool enable) int msm_dsi_host_power_on(struct mipi_dsi_host *host, struct msm_dsi_phy_shared_timings *phy_shared_timings, - bool is_dual_dsi) + bool
Re: [Freedreno] [PATCH] drm/msm/dsi: add support for dsi test pattern generator
Hi Marijn Thanks for reviewing and testing the latest patchset. On 2021-08-10 15:59, Marijn Suijten wrote: Hi Abhinav, On 7/16/21 2:01 AM, abhin...@codeaurora.org wrote: Hi Marijn Sorry for the late response. Apologies from my side as well. [...] +static void msm_dsi_host_cmd_test_pattern_setup(struct msm_dsi_host *msm_host) +{ + u32 reg; + + reg = dsi_read(msm_host, REG_DSI_TEST_PATTERN_GEN_CTRL); + + dsi_write(msm_host, REG_DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL0, 0xff); + + reg |= (0x3 << 0x8); + dsi_write(msm_host, REG_DSI_TEST_PATTERN_GEN_CTRL, reg); + /* draw checkered rectangle pattern */ + dsi_write(msm_host, REG_DSI_TPG_MAIN_CONTROL2, (0x1 << 0x7)); How about BIT(7)? You mean BIT(7) of REG_DSI_TPG_MAIN_CONTROL2? Thats what this is right? Did you mean some other bit? I meant to replace (0x1 << 0x7) with BIT(7), but replacing it with DSI_TPG_MAIN_CONTROL2_CMD_MDP0_CHECKERED_RECTANGLE_PATTERN is even better, thanks. On SM6125 this seems to change the color intensity of the pattern; it is always colored lines of a few pixels wide alternating R, B and G from left to right. Is it possible to document the meaning and available values of these registers, especially if they differ between SoC / DSI block? I have requested access for SM6125, will check this register on that to see if there is any difference. Are you saying you are not seeing a rectangular checkered pattern while testing? Correct. It's fixed now, and this patch already proves its usefulness! We had two minor configuration issues, and are now seeing the squares just like on the other SoCs. Meaning we can finally move on to configuring the DPU, thanks! Thats good to know ! Also are you testing on command mode or video mode? Command mode, if it's still worth anything. Thats good to know too, as I had not been able to test command mode. As requested by Rob, I will add the bit definitions and update the dsi.xml.h in the next patchset for the registers and the bits which I am using here. With that the meaning of these bits will be more clear. I dont think I will be able to document all the bits because the goal of this patch was only to draw a test pattern to help with validation. Different bits of the REG_DSI_TPG_MAIN_CONTROL2 register only draw different patterns so the goal wasnt that we can draw any pattern, it was just to draw some pattern on the screen. When we add support for all other patterns, we can expose those bits as well but it should not be required in my opinion. Understandable. I'm curious if other patterns are useful in certain situations, like DSC? Other than that, knowing that the DSI and PHY is correct is good enough for us. The TPG in this patch is only for the DSI block which is after the DSC block. So any pattern we pick from the DSI_TPG_MAIN_CONTROL2 register (using any other bit) will only look different visually but will still be from DSI and no other block. So it will not help to validate DSC block individually. Kind regards, Marijn + DBG("Cmd test pattern setup done\n"); +} [...] Thanks! Marijn
Re: [Freedreno] [PATCH v2 07/14] drm/msm: Convert to Linux IRQ interfaces
On 2021-08-03 02:06, Thomas Zimmermann wrote: Drop the DRM IRQ midlayer in favor of Linux IRQ interfaces. DRM's IRQ helpers are mostly useful for UMS drivers. Modern KMS drivers don't benefit from using it. DRM IRQ callbacks are now being called directly or inlined. Signed-off-by: Thomas Zimmermann Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/msm_drv.c | 113 -- drivers/gpu/drm/msm/msm_kms.h | 2 +- 2 files changed, 69 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 1594ae39d54f..a332b09a5a11 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -201,6 +200,71 @@ void msm_rmw(void __iomem *addr, u32 mask, u32 or) msm_writel(val | or, addr); } +static irqreturn_t msm_irq(int irq, void *arg) +{ + struct drm_device *dev = arg; + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + + BUG_ON(!kms); + + return kms->funcs->irq(kms); +} + +static void msm_irq_preinstall(struct drm_device *dev) +{ + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + + BUG_ON(!kms); + + kms->funcs->irq_preinstall(kms); +} + +static int msm_irq_postinstall(struct drm_device *dev) +{ + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + + BUG_ON(!kms); + + if (kms->funcs->irq_postinstall) + return kms->funcs->irq_postinstall(kms); + + return 0; +} + +static int msm_irq_install(struct drm_device *dev, unsigned int irq) +{ + int ret; + + if (irq == IRQ_NOTCONNECTED) + return -ENOTCONN; + + msm_irq_preinstall(dev); + + ret = request_irq(irq, msm_irq, 0, dev->driver->name, dev); + if (ret) + return ret; + + ret = msm_irq_postinstall(dev); + if (ret) { + free_irq(irq, dev); + return ret; + } + + return 0; +} + +static void msm_irq_uninstall(struct drm_device *dev) +{ + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + + kms->funcs->irq_uninstall(kms); + free_irq(kms->irq, dev); +} + struct msm_vblank_work { struct work_struct work; int crtc_id; @@ -265,7 +329,7 @@ static int msm_drm_uninit(struct device *dev) } /* We must cancel and cleanup any pending vblank enable/disable -* work before drm_irq_uninstall() to avoid work re-enabling an +* work before msm_irq_uninstall() to avoid work re-enabling an * irq after uninstall has disabled it. */ @@ -294,7 +358,7 @@ static int msm_drm_uninit(struct device *dev) drm_mode_config_cleanup(ddev); pm_runtime_get_sync(dev); - drm_irq_uninstall(ddev); + msm_irq_uninstall(ddev); pm_runtime_put_sync(dev); if (kms && kms->funcs) @@ -553,7 +617,7 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) if (kms) { pm_runtime_get_sync(dev); - ret = drm_irq_install(ddev, kms->irq); + ret = msm_irq_install(ddev, kms->irq); pm_runtime_put_sync(dev); if (ret < 0) { DRM_DEV_ERROR(dev, "failed to install IRQ handler\n"); @@ -662,43 +726,6 @@ static void msm_postclose(struct drm_device *dev, struct drm_file *file) context_close(ctx); } -static irqreturn_t msm_irq(int irq, void *arg) -{ - struct drm_device *dev = arg; - struct msm_drm_private *priv = dev->dev_private; - struct msm_kms *kms = priv->kms; - BUG_ON(!kms); - return kms->funcs->irq(kms); -} - -static void msm_irq_preinstall(struct drm_device *dev) -{ - struct msm_drm_private *priv = dev->dev_private; - struct msm_kms *kms = priv->kms; - BUG_ON(!kms); - kms->funcs->irq_preinstall(kms); -} - -static int msm_irq_postinstall(struct drm_device *dev) -{ - struct msm_drm_private *priv = dev->dev_private; - struct msm_kms *kms = priv->kms; - BUG_ON(!kms); - - if (kms->funcs->irq_postinstall) - return kms->funcs->irq_postinstall(kms); - - return 0; -} - -static void msm_irq_uninstall(struct drm_device *dev) -{ - struct msm_drm_private *priv = dev->dev_private; - struct msm_kms *kms = priv->kms; - BUG_ON(!kms); - kms->funcs->irq_uninstall(kms); -} - int msm_crtc_enable_vblank(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -1051,10 +1078,6 @@ static const struct drm_driver msm_driver = { .open = msm_open, .postclose = msm_postclose, .lastclose = drm_fb_helper_lastclose, - .irq_handler= msm_irq,
Re: [Freedreno] [PATCH 11/11] drm/msm/dsi: Pass DSC params to drm_panel
On 2021-07-14 23:52, Vinod Koul wrote: When DSC is enabled, we need to pass the DSC parameters to panel driver as well, so add a dsc parameter in panel and set it when DSC is enabled Signed-off-by: Vinod Koul based on the comments on prev patches in the series, this will need to be reworked too as there wont be any priv->dsc anymore. Also, can you also post the panel changes? Would like to see how you will use the dsc param there. --- drivers/gpu/drm/msm/dsi/dsi_host.c | 16 +++- include/drm/drm_panel.h| 7 +++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 4e8ab1b1df8b..ee21cda243a7 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -2193,6 +2193,7 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; struct platform_device *pdev = msm_host->pdev; struct msm_drm_private *priv; + struct drm_panel *panel; int ret; msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); @@ -2212,8 +2213,21 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, } msm_host->dev = dev; + panel = msm_dsi_host_get_panel(_host->base); priv = dev->dev_private; - priv->dsc = msm_host->dsc; + + if (panel && panel->dsc) { + struct msm_display_dsc_config *dsc = priv->dsc; + + if (!dsc) { + dsc = kzalloc(sizeof(*dsc), GFP_KERNEL); + if (!dsc) + return -ENOMEM; + dsc->drm = panel->dsc; + priv->dsc = dsc; + msm_host->dsc = dsc; + } + } ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); if (ret) { diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 33605c3f0eba..27a7808a29f2 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -171,6 +171,13 @@ struct drm_panel { * Panel entry in registry. */ struct list_head list; + + /** +* @dsc: +* +* Panel DSC pps payload to be sent +*/ + struct drm_dsc_config *dsc; }; void drm_panel_init(struct drm_panel *panel, struct device *dev,
Re: [Freedreno] [PATCH 10/11] drm/msm/dsi: Add support for DSC configuration
On 2021-07-14 23:52, Vinod Koul wrote: When DSC is enabled, we need to configure DSI registers accordingly and configure the respective stream compression registers. Add support to calculate the register setting based on DSC params and timing information and configure these registers. Signed-off-by: Vinod Koul same comments as dmitry on this one: https://patchwork.freedesktop.org/patch/444082/?series=90413=2 nothing more to add. --- drivers/gpu/drm/msm/dsi/dsi.xml.h | 10 ++ drivers/gpu/drm/msm/dsi/dsi_host.c | 142 +++-- 2 files changed, 142 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h index 50eb4d1b8fdd..b8e9e608abfc 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.xml.h +++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h @@ -2310,4 +2310,14 @@ static inline uint32_t REG_DSI_7nm_PHY_LN_TX_DCTRL(uint32_t i0) { return 0x0 #define REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE 0x0260 +#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL0x029c + +#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL2 0x02a0 + +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL 0x02a4 + +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2 0x02a8 + +#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL3 0x02ac + #endif /* DSI_XML */ diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index e1e5d91809b5..4e8ab1b1df8b 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -942,6 +942,26 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, dsi_write(msm_host, REG_DSI_CTRL, data); } +static int dsi_dsc_update_pic_dim(struct msm_display_dsc_config *dsc, + int pic_width, int pic_height) +{ + if (!dsc || !pic_width || !pic_height) { + pr_err("DSI: invalid input: pic_width: %d pic_height: %d\n", pic_width, pic_height); + return -EINVAL; + } + + if ((pic_width % dsc->drm->slice_width) || (pic_height % dsc->drm->slice_height)) { + pr_err("DSI: pic_dim %dx%d has to be multiple of slice %dx%d\n", + pic_width, pic_height, dsc->drm->slice_width, dsc->drm->slice_height); + return -EINVAL; + } + + dsc->drm->pic_width = pic_width; + dsc->drm->pic_height = pic_height; + + return 0; +} + static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) { struct drm_display_mode *mode = msm_host->mode; @@ -956,6 +976,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) u32 va_end = va_start + mode->vdisplay; u32 hdisplay = mode->hdisplay; u32 wc; + u32 data; DBG(""); @@ -974,7 +995,73 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) hdisplay /= 2; } + if (msm_host->dsc) { + struct msm_display_dsc_config *dsc = msm_host->dsc; + + /* update dsc params with timing params */ + dsi_dsc_update_pic_dim(dsc, mode->hdisplay, mode->vdisplay); + DBG("Mode Width- %d x Height %d\n", dsc->drm->pic_width, dsc->drm->pic_height); + + /* we do the calculations for dsc parameters here so that +* panel can use these parameters +*/ + dsi_populate_dsc_params(dsc); + + /* Divide the display by 3 but keep back/font porch and +* pulse width same +*/ + h_total -= hdisplay; + hdisplay /= 3; + h_total += hdisplay; + ha_end = ha_start + hdisplay; + } + if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) { + if (msm_host->dsc) { + struct msm_display_dsc_config *dsc = msm_host->dsc; + u32 reg, intf_width, slice_per_intf, width; + u32 total_bytes_per_intf; + + /* first calculate dsc parameters and then program +* compress mode registers +*/ + intf_width = hdisplay; + slice_per_intf = DIV_ROUND_UP(intf_width, dsc->drm->slice_width); + + /* If slice_count > slice_per_intf, then use 1 +* This can happen during partial update +*/ + dsc->drm->slice_count = 1; + + dsc->bytes_in_slice = DIV_ROUND_UP(dsc->drm->slice_width * 8, 8); + total_bytes_per_intf = dsc->bytes_in_slice * slice_per_intf; + + dsc->eol_byte_num = total_bytes_per_intf % 3; + dsc->pclk_per_line = DIV_ROUND_UP(total_bytes_per_intf, 3); +
Re: [Freedreno] [PATCH 09/11] drm/msm/disp/dpu1: Add support for DSC in topology
On 2021-07-14 23:52, Vinod Koul wrote: For DSC to work we typically need a 2,2,1 configuration. This should suffice for resolutions upto 4k. For more resolutions like 8k this won't work. The topology information is provided by DTS so we try to deduce the topology required for DSC. Furthermore, we can use 1 DSC encoder in lesser resolutions, but that is not power efficient according to Abhinav, it is better to use 2 mixers as that will split width/2 and is proven to be power efficient. I think now that we have added the technical reason of why it is better to use 2-2-1 ( using 2 LMs is better than one as it will half layer width), we can drop my name from the commit text as it holds less value than the actual reason itself :) You can still keep my signed-off and co-developed by tag Also, the panel has been tested only with 2,2,1 configuration, so for now we blindly create 2,2,1 topology when DSC is enabled Co-developed-by: Abhinav Kumar Signed-off-by: Abhinav Kumar Signed-off-by: Vinod Koul --- Changes since RFC: - Add more details in changelog drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 16 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 41140b781e66..8f0a8bd9c8ff 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -573,6 +573,8 @@ static struct msm_display_topology dpu_encoder_get_topology( struct drm_display_mode *mode) { struct msm_display_topology topology = {0}; + struct drm_encoder *drm_enc; + struct msm_drm_private *priv; int i, intf_count = 0; for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++) @@ -607,8 +609,22 @@ static struct msm_display_topology dpu_encoder_get_topology( topology.num_enc = 0; topology.num_intf = intf_count; + drm_enc = _enc->base; + priv = drm_enc->dev->dev_private; + if (priv && priv->dsc) { if dsc is moved to the encoder, this will need to be changed too + /* In case of Display Stream Compression DSC, we would use +* 2 encoders, 2 line mixers and 1 interface +* this is power optimal and can drive upto (including) 4k +* screens +*/ + topology.num_enc = 2; + topology.num_intf = 1; + topology.num_lm = 2; + } + return topology; } + static int dpu_encoder_virt_atomic_check( struct drm_encoder *drm_enc, struct drm_crtc_state *crtc_state,
Re: [Freedreno] [PATCH 08/11] drm/msm/disp/dpu1: Add support for DSC in encoder
On 2021-07-14 23:52, Vinod Koul wrote: When DSC is enabled in DT, we need to configure the encoder for DSC configuration, calculate DSC parameters for the given timing. This patch adds that support by adding dpu_encoder_prep_dsc() which is invoked when DSC is enabled in DT correct me if wrong but this commit text is not valid anymore in my opinion. are there any params you are getting from DT now? I thought its all coming from the panel driver directly. Signed-off-by: Vinod Koul agree with dmitry's comment's https://patchwork.freedesktop.org/patch/444078/?series=90413=2 instead of dsc being part of priv->dsc it should be per encoder. On top of his comment, I also think that like on the newer chipsets, moving the dsc related encoder configuration to a dpu_encoder_dce.c will help for future expansion of other topologies and also for other compression algorithms. --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 142 +++- 1 file changed, 141 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 8d942052db8a..41140b781e66 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -21,12 +21,17 @@ #include "dpu_hw_intf.h" #include "dpu_hw_ctl.h" #include "dpu_hw_dspp.h" +#include "dpu_hw_dsc.h" #include "dpu_formats.h" #include "dpu_encoder_phys.h" #include "dpu_crtc.h" #include "dpu_trace.h" #include "dpu_core_irq.h" +#define DSC_MODE_SPLIT_PANEL BIT(0) +#define DSC_MODE_MULTIPLEX BIT(1) +#define DSC_MODE_VIDEO BIT(2) + #define DPU_DEBUG_ENC(e, fmt, ...) DPU_DEBUG("enc%d " fmt,\ (e) ? (e)->base.base.id : -1, ##__VA_ARGS__) @@ -135,6 +140,7 @@ enum dpu_enc_rc_states { * @cur_slave: As above but for the slave encoder. * @hw_pp: Handle to the pingpong blocks used for the display. No. * pingpong blocks can be different than num_phys_encs. + * @hw_dsc Handle to the DSC blocks used for the display. * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped * for partial update right-only cases, such as pingpong * split where virtual pingpong does not generate IRQs @@ -180,6 +186,7 @@ struct dpu_encoder_virt { struct dpu_encoder_phys *cur_master; struct dpu_encoder_phys *cur_slave; struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC]; + struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC]; bool intfs_swapped; @@ -1008,7 +1015,8 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC]; struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC]; struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL }; - int num_lm, num_ctl, num_pp; + struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC]; + int num_lm, num_ctl, num_pp, num_dsc; int i, j; if (!drm_enc) { @@ -1061,11 +1069,16 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, dpu_rm_get_assigned_resources(_kms->rm, global_state, drm_enc->base.id, DPU_HW_BLK_DSPP, hw_dspp, ARRAY_SIZE(hw_dspp)); + num_dsc = dpu_rm_get_assigned_resources(_kms->rm, global_state, + drm_enc->base.id, DPU_HW_BLK_DSC, hw_dsc, ARRAY_SIZE(hw_dsc)); for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i]) : NULL; + for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) + dpu_enc->hw_dsc[i] = i < num_dsc ? to_dpu_hw_dsc(hw_dsc[i]) : NULL; + cstate = to_dpu_crtc_state(drm_crtc->state); for (i = 0; i < num_lm; i++) { @@ -1810,10 +1823,133 @@ static void dpu_encoder_vsync_event_work_handler(struct kthread_work *work) nsecs_to_jiffies(ktime_to_ns(wakeup_time))); } +static void +dpu_encoder_dsc_pclk_param_calc(struct msm_display_dsc_config *dsc, u32 width) +{ + int slice_count, slice_per_intf; + int bytes_in_slice, total_bytes_per_intf; + + if (!dsc || !dsc->drm->slice_width || !dsc->drm->slice_count) { + DPU_ERROR("Invalid DSC/slices\n"); + return; + } + + slice_count = dsc->drm->slice_count; + slice_per_intf = DIV_ROUND_UP(width, dsc->drm->slice_width); + + /* +* If slice_count is greater than slice_per_intf then default to 1. +* This can happen during partial update. +*/ + if (slice_count > slice_per_intf) + slice_count = 1; + + bytes_in_slice = DIV_ROUND_UP(dsc->drm->slice_width * + dsc->drm->bits_per_pixel, 8); + total_bytes_per_intf = bytes_in_slice * slice_per_intf; + + dsc->eol_byte_num =
Re: [Freedreno] [PATCH 07/11] drm/msm/disp/dpu1: Don't use DSC with mode_3d
On 2021-07-14 23:51, Vinod Koul wrote: We cannot enable mode_3d when we are using the DSC. So pass configuration to detect DSC is enabled and not enable mode_3d when we are using DSC We add a helper dpu_encoder_helper_get_dsc_mode() to detect dsc enabled and pass this to .setup_intf_cfg() This is not entirely correct. This is true only for the 2-2-1 topology you are using on this panel. When you are using 2-2-1, you are using 2 LMs, 2 DSCs and 1 DSI. So 3D mux shouldnt be used. If you are using something like 4-2-1 or 4-2-2, then you have 4LMs, 2 DSCs and 2/1 DSI. Here you need the 3D mux to convert the data from 4LMs to 2 DSCs. So please correct the commit text here and also add a check for the topology. Signed-off-by: Vinod Koul --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 11 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 2 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 5 +++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 2 ++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index ecbc4be98980..d43b804528eb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -336,6 +336,17 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode( return BLEND_3D_NONE; } +static inline bool dpu_encoder_helper_get_dsc_mode(struct dpu_encoder_phys *phys_enc) +{ + struct drm_encoder *drm_enc = phys_enc->parent; + struct msm_drm_private *priv = drm_enc->dev->dev_private; + + if (priv->dsc) + return true; + + return false; +} Check whether DSC is enabled and only if its 2-2-1 topology. This needs to be reworked when other topologies are supported. + /** * dpu_encoder_helper_split_config - split display configuration helper function * This helper function may be used by physical encoders to configure diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c index b2be39b9144e..5fe87881c30c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c @@ -69,6 +69,8 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg( intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD; intf_cfg.stream_sel = cmd_enc->stream_sel; intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); + intf_cfg.dsc = dpu_encoder_helper_get_dsc_mode(phys_enc); + ctl->ops.setup_intf_cfg(ctl, _cfg); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index aeea6add61ee..f059416311ee 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -121,7 +121,7 @@ static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl *ctx) return ctx->pending_flush_mask; } -static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx) +static void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx) { DPU_REG_WRITE(>hw, CTL_DSC_FLUSH, BIT(0) | BIT(1) | BIT(2) | BIT(3)); @@ -522,7 +522,8 @@ static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx, intf_cfg |= (cfg->intf & 0xF) << 4; - if (cfg->mode_3d) { + /* In DSC we can't set merge, so check for dsc too */ + if (cfg->mode_3d && !cfg->dsc) { intf_cfg |= BIT(19); intf_cfg |= (cfg->mode_3d - 0x1) << 20; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h index 806c171e5df2..347a653c1e01 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h @@ -39,6 +39,7 @@ struct dpu_hw_stage_cfg { * @mode_3d: 3d mux configuration * @merge_3d: 3d merge block used * @intf_mode_sel: Interface mode, cmd / vid + * @dsc: DSC is enabled * @stream_sel:Stream selection for multi-stream interfaces */ struct dpu_hw_intf_cfg { @@ -46,6 +47,7 @@ struct dpu_hw_intf_cfg { enum dpu_3d_blend_mode mode_3d; enum dpu_merge_3d merge_3d; enum dpu_ctl_mode_sel intf_mode_sel; + bool dsc; int stream_sel; };