Re: [PATCH 1/6] drm/ttm: move the LRU into resource handling v3
Adding a few more people. Just a gentle ping on this, can I get an rb or at least acked-by for this patch set? Thanks in advance, Christian. Am 15.02.22 um 18:22 schrieb Christian König: This way we finally fix the problem that new resource are not immediately evict-able after allocation. That has caused numerous problems including OOM on GDS handling and not being able to use TTM as general resource manager. v2: stop assuming in ttm_resource_fini that res->bo is still valid. v3: cleanup kerneldoc, add more lockdep annotation Signed-off-by: Christian König Tested-by: Bas Nieuwenhuizen --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 8 +- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 2 +- drivers/gpu/drm/ttm/ttm_bo.c| 115 ++ drivers/gpu/drm/ttm/ttm_bo_util.c | 1 - drivers/gpu/drm/ttm/ttm_device.c| 64 ++--- drivers/gpu/drm/ttm/ttm_resource.c | 122 +++- include/drm/ttm/ttm_bo_api.h| 16 include/drm/ttm/ttm_bo_driver.h | 29 +- include/drm/ttm/ttm_resource.h | 35 +++ 9 files changed, 197 insertions(+), 195 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index b37fc7d7d2c7..f2ce5a0defd9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -683,12 +683,12 @@ void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev, if (vm->bulk_moveable) { spin_lock(>mman.bdev.lru_lock); - ttm_bo_bulk_move_lru_tail(>lru_bulk_move); + ttm_lru_bulk_move_tail(>lru_bulk_move); spin_unlock(>mman.bdev.lru_lock); return; } - memset(>lru_bulk_move, 0, sizeof(vm->lru_bulk_move)); + ttm_lru_bulk_move_init(>lru_bulk_move); spin_lock(>mman.bdev.lru_lock); list_for_each_entry(bo_base, >idle, vm_status) { @@ -698,11 +698,9 @@ void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev, if (!bo->parent) continue; - ttm_bo_move_to_lru_tail(>tbo, bo->tbo.resource, - >lru_bulk_move); + ttm_bo_move_to_lru_tail(>tbo, >lru_bulk_move); if (shadow) ttm_bo_move_to_lru_tail(>tbo, - shadow->tbo.resource, >lru_bulk_move); } spin_unlock(>mman.bdev.lru_lock); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index de3fe79b665a..582e8dc9bc8c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -849,7 +849,7 @@ void i915_ttm_adjust_lru(struct drm_i915_gem_object *obj) bo->priority = I915_TTM_PRIO_NO_PAGES; } - ttm_bo_move_to_lru_tail(bo, bo->resource, NULL); + ttm_bo_move_to_lru_tail(bo, NULL); spin_unlock(>bdev->lru_lock); } diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index db3dc7ef5382..cb0fa932d495 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -69,108 +69,16 @@ static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, } } -static inline void ttm_bo_move_to_pinned(struct ttm_buffer_object *bo) -{ - struct ttm_device *bdev = bo->bdev; - - list_move_tail(>lru, >pinned); - - if (bdev->funcs->del_from_lru_notify) - bdev->funcs->del_from_lru_notify(bo); -} - -static inline void ttm_bo_del_from_lru(struct ttm_buffer_object *bo) -{ - struct ttm_device *bdev = bo->bdev; - - list_del_init(>lru); - - if (bdev->funcs->del_from_lru_notify) - bdev->funcs->del_from_lru_notify(bo); -} - -static void ttm_bo_bulk_move_set_pos(struct ttm_lru_bulk_move_pos *pos, -struct ttm_buffer_object *bo) -{ - if (!pos->first) - pos->first = bo; - pos->last = bo; -} - void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo, -struct ttm_resource *mem, struct ttm_lru_bulk_move *bulk) { - struct ttm_device *bdev = bo->bdev; - struct ttm_resource_manager *man; - - if (!bo->deleted) - dma_resv_assert_held(bo->base.resv); - - if (bo->pin_count) { - ttm_bo_move_to_pinned(bo); - return; - } - - if (!mem) - return; - - man = ttm_manager_type(bdev, mem->mem_type); - list_move_tail(>lru, >lru[bo->priority]); - - if (bdev->funcs->del_from_lru_notify) - bdev->funcs->del_from_lru_notify(bo); - - if (bulk && !bo->pin_count) { - switch (bo->resource->mem_type) { - case TTM_PL_TT: -
Re: [PATCH v2] drm/i915: fix build issue when using clang
On Tue, 15 Feb 2022, Nathan Chancellor wrote: > On Mon, Feb 14, 2022 at 11:58:20AM -0800, Tong Zhang wrote: >> drm/i915 adds some extra cflags, namely -Wall, which causes >> instances of -Wformat-security to appear when building with clang, even >> though this warning is turned off kernel-wide in the main Makefile: >> >> > drivers/gpu/drm/i915/gt/intel_gt.c:983:2: error: format string is not a >> > string literal (potentially insecure) [-Werror,-Wformat-security] >> > GEM_TRACE("ERROR\n"); >> > ^~~~ >> > ./drivers/gpu/drm/i915/i915_gem.h:76:24: note: expanded from macro >> > 'GEM_TRACE' >> > #define GEM_TRACE(...) trace_printk(__VA_ARGS__) >> >^ >> > ./include/linux/kernel.h:369:3: note: expanded from macro 'trace_printk' >> > do_trace_printk(fmt, ##__VA_ARGS__);\ >> > ^~~ >> > ./include/linux/kernel.h:383:30: note: expanded from macro >> > 'do_trace_printk' >> > __trace_bprintk(_THIS_IP_, trace_printk_fmt, ##args); \ >> > ^~~~ >> >drivers/gpu/drm/i915/gt/intel_gt.c:983:2: note: treat the string as an >> >argument to avoid this >> >> This does not happen with GCC because it does not enable >> -Wformat-security with -Wall. Disable -Wformat-security within the i915 >> Makefile so that these warnings do not show up with clang. >> >> Signed-off-by: Tong Zhang > > Given this is not enabled for GCC and it is disabled in the main > Makefile: > > Reviewed-by: Nathan Chancellor > > Additionally, it seems like trace_printk() is designed to be able to > take a string literal without a format argument, so this should be fine. Thanks for the patch and review, pushed to drm-intel-next. I appreciate the support in maintaining fairly strict warning levels in i915. BR, Jani. > >> --- >> >> v2: revise commit message >> >> drivers/gpu/drm/i915/Makefile | 1 + >> 1 file changed, 1 insertion(+) >> >> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile >> index 1b62b9f65196..c04e05a3d39f 100644 >> --- a/drivers/gpu/drm/i915/Makefile >> +++ b/drivers/gpu/drm/i915/Makefile >> @@ -13,6 +13,7 @@ >> # will most likely get a sudden build breakage... Hopefully we will fix >> # new warnings before CI updates! >> subdir-ccflags-y := -Wall -Wextra >> +subdir-ccflags-y += -Wno-format-security >> subdir-ccflags-y += -Wno-unused-parameter >> subdir-ccflags-y += -Wno-type-limits >> subdir-ccflags-y += -Wno-missing-field-initializers >> -- >> 2.25.1 >> >> -- Jani Nikula, Intel Open Source Graphics Center
[PATCH] drm/bridge: Clear the DP_AUX_I2C_MOT bit passed in aux command.
It's observed that if the previous transfer didn't end with a command without DP_AUX_I2C_MOT, the next trasnfer will miss the first byte. But if the command in previous transfer is requested with length 0, anx7625 can't process this command. To make the case simpler, request with commands without DP_AUX_I2C_MOT bit. Fixes: adca62ec370c ("drm/bridge: anx7625: Support reading edid through aux channel") Signed-off-by: Hsin-Yi Wang --- drivers/gpu/drm/bridge/analogix/anx7625.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 633618bafd75d3..050616c1162128 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -1703,7 +1703,7 @@ static ssize_t anx7625_aux_transfer(struct drm_dp_aux *aux, ret = -EINVAL; } if (!ret) - ret = anx7625_aux_trans(ctx, msg->request, msg->address, + ret = anx7625_aux_trans(ctx, request, msg->address, msg->size, msg->buffer); pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); -- 2.35.1.265.g69c8d7142f-goog
Re: [REPOST PATCH v4 08/13] drm/msm/disp/dpu1: Don't use DSC with mode_3d
On 17/02/2022 09:33, Abhinav Kumar wrote: On 2/16/2022 10:10 PM, Vinod Koul wrote: On 16-02-22, 19:11, Abhinav Kumar wrote: On 2/10/2022 2:34 AM, 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() to detect dsc enabled and pass this to .setup_intf_cfg() Signed-off-by: Vinod Koul We should not use 3D mux only when we use DSC merge topology. I agree that today we use only 2-2-1 topology for DSC which means its using DSC merge. But generalizing that 3D mux should not be used for DSC is not right. You can detect DSC merge by checking if there are two encoders and one interface in the topology and if so, you can disable 3D mux. Right now with DSC we disable that as suggested by Dmitry last time. Whenever we introduce merge we should revisit this, for now this should suffice Sorry I didnt follow. The topology which you are supporting today IS DSC merge 2-2-1. I didnt get what you mean by "whenever we introduce". I didnt follow Dmitry's comment either. "anybody adding support for SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC handle this." 3D mux shouldnt be used when DSC merge is used. The topology Dmitry is referring to will not use DSC merge but you are using it here and thats why you had to make this patch in the first place. So I am not sure why would someone who uses 3D merge topology worry about DSC merge. Your patch is the one which deals with the topology in question. What I am suggesting is a small but necessary improvement to this patch. It seems that we can replace this patch by changing dpu_encoder_helper_get_3d_blend_mode() to contain the following condition (instead of the one present there). Does the following seem correct to you: static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode( struct dpu_encoder_phys *phys_enc) { struct dpu_crtc_state *dpu_cstate; if (!phys_enc || phys_enc->enable_state == DPU_ENC_DISABLING) return BLEND_3D_NONE; dpu_cstate = to_dpu_crtc_state(phys_enc->parent->crtc->state); + /* Use merge_3d unless DSCMERGE topology is used */ if (phys_enc->split_role == ENC_ROLE_SOLO && + hweight(dpu_encoder_helper_get_dsc(phys_enc)) != 1 && dpu_cstate->num_mixers == CRTC_DUAL_MIXERS) return BLEND_3D_H_ROW_INT; return BLEND_3D_NONE; } All that you have to do is in query whether DSC merge is used from the topology. You can do it in multiple ways: 1) Either query this from the encoder 2) Store a bool "dsc_merge" in the intf_cfg -- With best wishes Dmitry
Re: [PATCH v7 3/4] drm/msm/dpu: replace BIT(x) with correspond marco define string
On 17/02/2022 01:05, Kuogee Hsieh wrote: To improve code readability, this patch replace BIT(x) with correspond register bit define string Signed-off-by: Kuogee Hsieh This patch should come first. --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 16 +++- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c index b68e696..8f10aab 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c @@ -61,6 +61,12 @@ #define INTF_MUX 0x25C +#define INTF_CFG_ACTIVE_H_ENBIT(29) +#define INTF_CFG_ACTIVE_V_ENBIT(30) + +#define INTF_CFG2_DATABUS_WIDEN BIT(0) +#define INTF_CFG2_DATA_HCTL_EN BIT(4) + static const struct dpu_intf_cfg *_intf_offset(enum dpu_intf intf, const struct dpu_mdss_cfg *m, void __iomem *addr, @@ -139,13 +145,13 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, if (active_h_end) { active_hctl = (active_h_end << 16) | active_h_start; - intf_cfg |= BIT(29); + intf_cfg |= INTF_CFG_ACTIVE_H_EN; } else { active_hctl = 0; } if (active_v_end) - intf_cfg |= BIT(30); + intf_cfg |= INTF_CFG_ACTIVE_V_EN; hsync_ctl = (hsync_period << 16) | p->hsync_pulse_width; display_hctl = (hsync_end_x << 16) | hsync_start_x; @@ -156,7 +162,7 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, * if compression is enabled in 1 pixel per clock mode */ if (p->wide_bus_en) - intf_cfg2 |= (BIT(0) | BIT(4)); + intf_cfg2 |= (INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN); data_width = p->width; @@ -178,8 +184,8 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, active_hctl = (active_h_end << 16) | active_h_start; display_hctl = active_hctl; - intf_cfg |= BIT(29); - intf_cfg |= BIT(30); + intf_cfg |= INTF_CFG_ACTIVE_H_EN; + intf_cfg |= INTF_CFG_ACTIVE_V_EN; } den_polarity = 0; -- With best wishes Dmitry
Re: [PATCH v7 4/4] drm/msm/dp: enable widebus feature for display port
On 17/02/2022 01:05, Kuogee Hsieh wrote: Widebus feature will transmit two pixel data per pixel clock to interface. This feature now is required to be enabled to easy migrant to higher resolution applications in future. However since some legacy chipsets does not support this feature, this feature is enabled base on chip's hardware revision. changes in v2: -- remove compression related code from timing -- remove op_info from struct msm_drm_private -- remove unnecessary wide_bus_en variables -- pass wide_bus_en into timing configuration by struct msm_dp Changes in v3: -- split patch into 3 patches -- enable widebus feature base on chip hardware revision Changes in v5: -- DP_INTF_CONFIG_DATABUS_WIDEN Changes in v6: -- fix Reported-bya issue -- fix static inline bool msm_dp_wide_bus_enable() at msm_drv.h Changes in v7: -- add Tested-by Signed-off-by: Kuogee Hsieh Reported-by: kernel test robot Tested-by: Bjorn Andersson --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 4 +++- drivers/gpu/drm/msm/dp/dp_catalog.c | 34 +++-- drivers/gpu/drm/msm/dp/dp_catalog.h | 3 ++- drivers/gpu/drm/msm/dp/dp_ctrl.c| 13 +++ drivers/gpu/drm/msm/dp/dp_ctrl.h| 1 + drivers/gpu/drm/msm/dp/dp_display.c | 32 +++ drivers/gpu/drm/msm/dp/dp_display.h | 2 ++ drivers/gpu/drm/msm/dp/dp_panel.c | 4 ++-- drivers/gpu/drm/msm/dp/dp_panel.h | 2 +- drivers/gpu/drm/msm/msm_drv.h | 6 + 10 files changed, 90 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 2b2dbb7..1e96cede 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2138,8 +2138,10 @@ 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) + else if (disp_info->intf_type == DRM_MODE_ENCODER_TMDS) { dpu_enc->dp = priv->dp[disp_info->h_tile_instance[0]]; + dpu_enc->wide_bus_en = msm_dp_wide_bus_enable(dpu_enc->dp); + } INIT_DELAYED_WORK(_enc->delayed_off_work, dpu_encoder_off_work); diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index 6ae9b29..524eccc 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -24,6 +24,8 @@ #define DP_INTERRUPT_STATUS_ACK_SHIFT 1 #define DP_INTERRUPT_STATUS_MASK_SHIFT2 +#define DP_INTF_CONFIG_DATABUS_WIDEN BIT(4) + #define DP_INTERRUPT_STATUS1 \ (DP_INTR_AUX_I2C_DONE| \ DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \ @@ -483,6 +485,22 @@ int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog, } /** + * dp_catalog_hw_revision() - retrieve DP hw revision + * + * @dp_catalog: DP catalog structure + * + * Return: DP controller hw revision + * + */ +u32 dp_catalog_hw_revision(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + return dp_read_ahb(catalog, REG_DP_HW_VERSION); +} + +/** * dp_catalog_ctrl_reset() - reset DP controller * * @dp_catalog: DP catalog structure @@ -739,10 +757,11 @@ u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog *dp_catalog) } /* panel related catalog functions */ -int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog) +int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog, bool wide_bus_en) { struct dp_catalog_private *catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog); + u32 reg; dp_write_link(catalog, REG_DP_TOTAL_HOR_VER, dp_catalog->total); @@ -751,7 +770,18 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog) dp_write_link(catalog, REG_DP_HSYNC_VSYNC_WIDTH_POLARITY, dp_catalog->width_blanking); dp_write_link(catalog, REG_DP_ACTIVE_HOR_VER, dp_catalog->dp_active); - dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, 0); + + reg = dp_read_p0(catalog, MMSS_DP_INTF_CONFIG); + + if (wide_bus_en) + reg |= DP_INTF_CONFIG_DATABUS_WIDEN; + else + reg &= ~DP_INTF_CONFIG_DATABUS_WIDEN; + + + DRM_DEBUG_DP("wide_bus_en=%d reg=%x\n", wide_bus_en, reg); + + dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, reg); return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h index 6965afa..2ba1ea4 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++
Re: [Intel-gfx] [PATCH] drm/i915: Kill the fake lmem support
On Wed, Feb 16, 2022 at 03:18:49PM -0800, Lucas De Marchi wrote: This was useful for early development of lmem, but it's not used anymore, so remove it. Cc: Chris Wilson Cc: Matthew Auld Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/i915/Kconfig.unstable | 8 -- drivers/gpu/drm/i915/gt/intel_gt.c | 2 - drivers/gpu/drm/i915/gt/intel_region_lmem.c | 112 +--- drivers/gpu/drm/i915/gt/intel_region_lmem.h | 3 - drivers/gpu/drm/i915/i915_driver.c | 15 --- drivers/gpu/drm/i915/i915_params.c | 5 - drivers/gpu/drm/i915/i915_params.h | 1 - 7 files changed, 2 insertions(+), 144 deletions(-) diff --git a/drivers/gpu/drm/i915/Kconfig.unstable b/drivers/gpu/drm/i915/Kconfig.unstable index 0c2276155c2b..cf151a297ed7 100644 --- a/drivers/gpu/drm/i915/Kconfig.unstable +++ b/drivers/gpu/drm/i915/Kconfig.unstable @@ -19,11 +19,3 @@ config DRM_I915_UNSTABLE Recommended for driver developers _only_. If in the slightest bit of doubt, say "N". - -config DRM_I915_UNSTABLE_FAKE_LMEM - bool "Enable the experimental fake lmem" - depends on DRM_I915_UNSTABLE - default n - help - Convert some system memory into a fake local memory region for - testing. diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index e8403fa53909..325ac15439eb 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -65,8 +65,6 @@ int intel_gt_probe_lmem(struct intel_gt *gt) int err; mem = intel_gt_setup_lmem(gt); - if (mem == ERR_PTR(-ENODEV)) - mem = intel_gt_setup_fake_lmem(gt); if (IS_ERR(mem)) { err = PTR_ERR(mem); if (err == -ENODEV) diff --git a/drivers/gpu/drm/i915/gt/intel_region_lmem.c b/drivers/gpu/drm/i915/gt/intel_region_lmem.c index cb3f66707b21..df3856e09598 100644 --- a/drivers/gpu/drm/i915/gt/intel_region_lmem.c +++ b/drivers/gpu/drm/i915/gt/intel_region_lmem.c @@ -13,60 +13,6 @@ #include "gem/i915_gem_ttm.h" #include "gt/intel_gt.h" -static int init_fake_lmem_bar(struct intel_memory_region *mem) -{ - struct drm_i915_private *i915 = mem->i915; - struct i915_ggtt *ggtt = to_gt(i915)->ggtt; - unsigned long n; - int ret; - - /* We want to 1:1 map the mappable aperture to our reserved region */ - - mem->fake_mappable.start = 0; - mem->fake_mappable.size = resource_size(>region); - mem->fake_mappable.color = I915_COLOR_UNEVICTABLE; I forgot to remove fake_mappable and remap_addr fields from the struct. I will send a v2 later if people agree to remove the fake lmem. Lucas De Marchi
Re: [Intel-gfx] [drm-tip:drm-tip 4/8] drivers/gpu/drm/solomon/ssd130x.c:451:18: error: incomplete definition of type 'struct dma_buf_map'
+Javier On Thu, Feb 17, 2022 at 02:25:08PM +0800, kernel test robot wrote: tree: git://anongit.freedesktop.org/drm/drm-tip drm-tip head: e141e36b2871c529379f7ec7d5d6ebae3137a51b commit: 7ca6504c36709f35c4cc38ae6acc1c9c3d72136f [4/8] Merge remote-tracking branch 'drm-misc/drm-misc-next' into drm-tip config: mips-buildonly-randconfig-r002-20220217 (https://download.01.org/0day-ci/archive/20220217/202202171455.bclm1ybc-...@intel.com/config) compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 0bad7cb56526f2572c74449fcf97c1fcda42b41d) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install mips cross compiling tool for clang build # apt-get install binutils-mips-linux-gnu git remote add drm-tip git://anongit.freedesktop.org/drm/drm-tip git fetch --no-tags drm-tip drm-tip git checkout 7ca6504c36709f35c4cc38ae6acc1c9c3d72136f # save the config file to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=mips SHELL=/bin/bash drivers/gpu/drm/solomon/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All error/warnings (new ones prefixed by >>): drivers/gpu/drm/solomon/ssd130x.c:447:74: warning: declaration of 'struct dma_buf_map' will not be visible outside of this function [-Wvisibility] static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf_map *map, ^ this is now called iosys_map in drm-intel... drm-tip will need a fixup for the merge. drivers/gpu/drm/solomon/ssd130x.c:451:18: error: incomplete definition of type 'struct dma_buf_map' void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */ ~~~^ this shouldn't really be done. Lucas De Marchi
Re: [PATCH v7 1/4] drm/msm/dpu: revise timing engine programming to support widebus feature
On 17/02/2022 01:05, Kuogee Hsieh wrote: Widebus feature will transmit two pixel data per pixel clock to interface. Timing engine provides driving force for this purpose. This patch base on HPG (Hardware Programming Guide) to revise timing engine register setting to accommodate both widebus and non widebus application. Also horizontal width parameters need to be reduced by half since two pixel data are clocked out per pixel clock when widebus feature enabled. Widebus can be enabled individually at DP. However at DSI, widebus have to be enabled along with DSC to achieve pixel clock rate be scaled down with same ratio as compression ratio when 10 bits per source component. Therefore this patch add no supports of DSI related widebus and compression. Changes in v2: -- remove compression related code from timing -- remove op_info from struct msm_drm_private -- remove unnecessary wide_bus_en variables -- pass wide_bus_en into timing configuration by struct msm_dp Changes in v3: -- split patch into 3 patches Changes in v4: -- rework timing engine to not interfere with dsi/hdmi -- cover both widebus and compression Changes in v5: -- remove supports of DSI widebus and compression Changes in v7: -- split this patch into 3 patches -- add Tested-by Signed-off-by: Kuogee Hsieh Tested-by: Bjorn Andersson --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c| 10 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h| 2 + .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 14 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c| 55 -- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h| 2 + 5 files changed, 68 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 1e648db..2b2dbb7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -208,6 +208,8 @@ struct dpu_encoder_virt { u32 idle_timeout; + bool wide_bus_en; + struct msm_dp *dp; }; @@ -217,6 +219,14 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = { 15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10 }; + +bool dpu_encoder_is_widebus_enabled(struct drm_encoder *drm_enc) +{ + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); + + return dpu_enc->wide_bus_en; +} + static void _dpu_encoder_setup_dither(struct dpu_hw_pingpong *hw_pp, unsigned bpc) { struct dpu_hw_dither_cfg dither_cfg = { 0 }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index e241914..0d73550 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -168,4 +168,6 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc); */ int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc); +bool dpu_encoder_is_widebus_enabled(struct drm_encoder *drm_enc); + #endif /* __DPU_ENCODER_H__ */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index ddd9d89..04ac2dc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -110,6 +110,20 @@ static void drm_mode_to_intf_timing_params( timing->v_back_porch += timing->v_front_porch; timing->v_front_porch = 0; } + + timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent); + + /* +* for DP, divide the horizonal parameters by 2 when +* widebus is enabled +*/ + if (phys_enc->hw_intf->cap->type == INTF_DP && timing->wide_bus_en) { + timing->width = timing->width >> 1; + timing->xres = timing->xres >> 1; + timing->h_back_porch = timing->h_back_porch >> 1; + timing->h_front_porch = timing->h_front_porch >> 1; + timing->hsync_pulse_width = timing->hsync_pulse_width >> 1; + } } static u32 get_horizontal_total(const struct intf_timing_params *timing) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c index 116e2b5..b68e696 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c @@ -33,6 +33,7 @@ #define INTF_TP_COLOR1 0x05C #define INTF_CONFIG20x060 #define INTF_DISPLAY_DATA_HCTL 0x064 +#define INTF_ACTIVE_DATA_HCTL 0x068 #define INTF_FRAME_LINE_COUNT_EN0x0A8 #define INTF_FRAME_COUNT0x0AC #define INTF_LINE_COUNT 0x0B0 @@ -90,15 +91,23 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, u32 hsync_period, vsync_period; u32 display_v_start, display_v_end; u32 hsync_start_x, hsync_end_x; + u32
Re: [REPOST PATCH v4 08/13] drm/msm/disp/dpu1: Don't use DSC with mode_3d
On 2/16/2022 10:10 PM, Vinod Koul wrote: On 16-02-22, 19:11, Abhinav Kumar wrote: On 2/10/2022 2:34 AM, 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() to detect dsc enabled and pass this to .setup_intf_cfg() Signed-off-by: Vinod Koul We should not use 3D mux only when we use DSC merge topology. I agree that today we use only 2-2-1 topology for DSC which means its using DSC merge. But generalizing that 3D mux should not be used for DSC is not right. You can detect DSC merge by checking if there are two encoders and one interface in the topology and if so, you can disable 3D mux. Right now with DSC we disable that as suggested by Dmitry last time. Whenever we introduce merge we should revisit this, for now this should suffice Sorry I didnt follow. The topology which you are supporting today IS DSC merge 2-2-1. I didnt get what you mean by "whenever we introduce". I didnt follow Dmitry's comment either. "anybody adding support for SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC handle this." 3D mux shouldnt be used when DSC merge is used. The topology Dmitry is referring to will not use DSC merge but you are using it here and thats why you had to make this patch in the first place. So I am not sure why would someone who uses 3D merge topology worry about DSC merge. Your patch is the one which deals with the topology in question. What I am suggesting is a small but necessary improvement to this patch. All that you have to do is in query whether DSC merge is used from the topology. You can do it in multiple ways: 1) Either query this from the encoder 2) Store a bool "dsc_merge" in the intf_cfg
[drm-tip:drm-tip 4/8] drivers/gpu/drm/solomon/ssd130x.c:451:18: error: incomplete definition of type 'struct dma_buf_map'
tree: git://anongit.freedesktop.org/drm/drm-tip drm-tip head: e141e36b2871c529379f7ec7d5d6ebae3137a51b commit: 7ca6504c36709f35c4cc38ae6acc1c9c3d72136f [4/8] Merge remote-tracking branch 'drm-misc/drm-misc-next' into drm-tip config: mips-buildonly-randconfig-r002-20220217 (https://download.01.org/0day-ci/archive/20220217/202202171455.bclm1ybc-...@intel.com/config) compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 0bad7cb56526f2572c74449fcf97c1fcda42b41d) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install mips cross compiling tool for clang build # apt-get install binutils-mips-linux-gnu git remote add drm-tip git://anongit.freedesktop.org/drm/drm-tip git fetch --no-tags drm-tip drm-tip git checkout 7ca6504c36709f35c4cc38ae6acc1c9c3d72136f # save the config file to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=mips SHELL=/bin/bash drivers/gpu/drm/solomon/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All error/warnings (new ones prefixed by >>): >> drivers/gpu/drm/solomon/ssd130x.c:447:74: warning: declaration of 'struct >> dma_buf_map' will not be visible outside of this function [-Wvisibility] static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf_map *map, ^ >> drivers/gpu/drm/solomon/ssd130x.c:451:18: error: incomplete definition of >> type 'struct dma_buf_map' void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */ ~~~^ drivers/gpu/drm/solomon/ssd130x.c:447:74: note: forward declaration of 'struct dma_buf_map' static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf_map *map, ^ >> drivers/gpu/drm/solomon/ssd130x.c:506:40: error: incompatible pointer types >> passing 'struct iosys_map *' to parameter of type 'const struct dma_buf_map >> *' [-Werror,-Wincompatible-pointer-types] ssd130x_fb_blit_rect(plane_state->fb, _plane_state->data[0], _state->dst); ^~~~ drivers/gpu/drm/solomon/ssd130x.c:447:87: note: passing argument to parameter 'map' here static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf_map *map, ^ drivers/gpu/drm/solomon/ssd130x.c:566:40: error: incompatible pointer types passing 'struct iosys_map *' to parameter of type 'const struct dma_buf_map *' [-Werror,-Wincompatible-pointer-types] ssd130x_fb_blit_rect(plane_state->fb, _plane_state->data[0], _clip); ^~~~ drivers/gpu/drm/solomon/ssd130x.c:447:87: note: passing argument to parameter 'map' here static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf_map *map, ^ 1 warning and 3 errors generated. vim +451 drivers/gpu/drm/solomon/ssd130x.c a61732e808672cf Javier Martinez Canillas 2022-02-14 446 a61732e808672cf Javier Martinez Canillas 2022-02-14 @447 static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf_map *map, a61732e808672cf Javier Martinez Canillas 2022-02-14 448 struct drm_rect *rect) a61732e808672cf Javier Martinez Canillas 2022-02-14 449 { a61732e808672cf Javier Martinez Canillas 2022-02-14 450struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev); a61732e808672cf Javier Martinez Canillas 2022-02-14 @451void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */ a61732e808672cf Javier Martinez Canillas 2022-02-14 452int ret = 0; a61732e808672cf Javier Martinez Canillas 2022-02-14 453u8 *buf = NULL; a61732e808672cf Javier Martinez Canillas 2022-02-14 454 a61732e808672cf Javier Martinez Canillas 2022-02-14 455buf = kcalloc(fb->width, fb->height, GFP_KERNEL); a61732e808672cf Javier Martinez Canillas 2022-02-14 456if (!buf) a61732e808672cf Javier Martinez Canillas 2022-02-14 457return -ENOMEM; a61732e808672cf Javier Martinez Canillas 2022-02-14 458 a61732e808672cf Javier Martinez Canillas 2022-02-14 459 drm_fb_xrgb_to_mono_reversed(buf, 0, vmap, fb, rect); a61732e808672cf Javier Martinez Canillas 2022-02-14 460 a61732e808672cf Javier Martinez Canillas 2022-02-14 461 ssd130x_update_rect(ssd130x, buf, rect); a61732e808672cf Javier Martinez
Re: [PATCH] drm/i915/guc/slpc: Use wrapper for reading RP_STATE_CAP
On Tue, Feb 15, 2022 at 06:58:17PM -0800, Vinay Belgaumkar wrote: > This will ensure correct values for Gen12+ platforms. > > Cc: Matt Roper > Signed-off-by: Vinay Belgaumkar Reviewed-by: Matt Roper > --- > drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > index 13b27b8ff74e..cf075e726699 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c > @@ -6,6 +6,7 @@ > #include "i915_drv.h" > #include "intel_guc_slpc.h" > #include "gt/intel_gt.h" > +#include "gt/intel_rps.h" > > static inline struct intel_guc *slpc_to_guc(struct intel_guc_slpc *slpc) > { > @@ -574,10 +575,10 @@ static int slpc_use_fused_rp0(struct intel_guc_slpc > *slpc) > > static void slpc_get_rp_values(struct intel_guc_slpc *slpc) > { > + struct intel_rps *rps = _to_gt(slpc)->rps; > u32 rp_state_cap; > > - rp_state_cap = intel_uncore_read(slpc_to_gt(slpc)->uncore, > - GEN6_RP_STATE_CAP); > + rp_state_cap = intel_rps_read_state_cap(rps); > > slpc->rp0_freq = REG_FIELD_GET(RP0_CAP_MASK, rp_state_cap) * > GT_FREQUENCY_MULTIPLIER; > -- > 2.34.0 > -- Matt Roper Graphics Software Engineer VTT-OSGC Platform Enablement Intel Corporation (916) 356-2795
Re: [Freedreno] [REPOST PATCH v4 13/13] drm/msm/dsi: Add support for DSC configuration
On 16-02-22, 19:44, Abhinav Kumar wrote: > > > On 2/10/2022 2:34 AM, 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: Dmitry Baryshkov > > Signed-off-by: Vinod Koul > > --- > > drivers/gpu/drm/msm/dsi/dsi.xml.h | 10 +++ > > drivers/gpu/drm/msm/dsi/dsi_host.c | 109 - > > 2 files changed, 118 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h > > b/drivers/gpu/drm/msm/dsi/dsi.xml.h > > index 49b551ad1bff..c1c85df58c4b 100644 > > --- a/drivers/gpu/drm/msm/dsi/dsi.xml.h > > +++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h > > @@ -706,4 +706,14 @@ static inline uint32_t DSI_VERSION_MAJOR(uint32_t val) > > #define REG_DSI_CPHY_MODE_CTRL > > 0x02d4 > > +#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL > > 0x029c > > + > > +#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 > > + > > This file should not be edited manually. The updates have to be generated > using the headergen tool. I have already send mesa patch for that. https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14967#note_1253974 You should chime in there as well :) I will split these and get these generated one as a separate patch.. > > > #endif /* DSI_XML */ > > diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c > > b/drivers/gpu/drm/msm/dsi/dsi_host.c > > index 438c80750682..3d8d5a1daaa3 100644 > > --- a/drivers/gpu/drm/msm/dsi/dsi_host.c > > +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c > > @@ -908,6 +908,20 @@ static void dsi_ctrl_config(struct msm_dsi_host > > *msm_host, bool enable, > > dsi_write(msm_host, REG_DSI_CPHY_MODE_CTRL, BIT(0)); > > } > > +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; > > + } > > + > > + 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_bonded_dsi) > > { > > struct drm_display_mode *mode = msm_host->mode; > > @@ -940,7 +954,68 @@ static void dsi_timing_setup(struct msm_dsi_host > > *msm_host, bool is_bonded_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; > > + 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); > > + > > + dsc->drm->slice_count = 1; > > Why is this hard-coded to 1 here? Am i missing something? > I think I need another day to look into these calculations. Thanks for spotting this, it should be: dsc->drm->slice_count = DIV_ROUND_UP(intf_width, dsc->drm->slice_widths); which is slice_per_intf so I will update this -- ~Vinod
Re: [REPOST PATCH v4 08/13] drm/msm/disp/dpu1: Don't use DSC with mode_3d
On 16-02-22, 19:11, Abhinav Kumar wrote: > > > On 2/10/2022 2:34 AM, 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() to detect dsc > > enabled and pass this to .setup_intf_cfg() > > > > Signed-off-by: Vinod Koul > > We should not use 3D mux only when we use DSC merge topology. > I agree that today we use only 2-2-1 topology for DSC which means its using > DSC merge. > > But generalizing that 3D mux should not be used for DSC is not right. > > You can detect DSC merge by checking if there are two encoders and one > interface in the topology and if so, you can disable 3D mux. Right now with DSC we disable that as suggested by Dmitry last time. Whenever we introduce merge we should revisit this, for now this should suffice -- ~Vinod
Re: [Freedreno] [REPOST PATCH v4 07/13] drm/msm/disp/dpu1: Add support for DSC in encoder
On 16-02-22, 11:54, Abhinav Kumar wrote: > > +/** > > + * dpu_encoder_helper_get_dsc - get DSC blocks mask for the DPU encoder > > + * This helper function is used by physical encoder to get DSC blocks > > mask > > + * used for this encoder. > > This looks slightly misaligned to me or not sure if its my mail client. > Please check it once. This looks fine in code as well as in mutt for me.. Maybe client issue -- ~Vinod
[PATCH v5 5/5] drm/msm/dp: rewrite dss_module_power to use bulk clock functions
In order to simplify DP code, drop hand-coded loops over clock arrays, replacing them with clk_bulk_* functions. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/Makefile | 1 - drivers/gpu/drm/msm/dp/dp_clk_util.c | 87 drivers/gpu/drm/msm/dp/dp_clk_util.h | 29 -- drivers/gpu/drm/msm/dp/dp_ctrl.c | 4 +- drivers/gpu/drm/msm/dp/dp_parser.c | 36 +--- drivers/gpu/drm/msm/dp/dp_parser.h | 6 +- drivers/gpu/drm/msm/dp/dp_power.c| 45 -- 7 files changed, 34 insertions(+), 174 deletions(-) delete mode 100644 drivers/gpu/drm/msm/dp/dp_clk_util.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_clk_util.h diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index a44abf0a7660..ecf01f9989ed 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -101,7 +101,6 @@ msm-$(CONFIG_DRM_MSM_GPU_STATE) += adreno/a6xx_gpu_state.o msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_catalog.o \ - dp/dp_clk_util.o \ dp/dp_ctrl.o \ dp/dp_display.o \ dp/dp_drm.o \ diff --git a/drivers/gpu/drm/msm/dp/dp_clk_util.c b/drivers/gpu/drm/msm/dp/dp_clk_util.c deleted file mode 100644 index 85abed31c68b.. --- a/drivers/gpu/drm/msm/dp/dp_clk_util.c +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2012-2015, 2017-2018, The Linux Foundation. - * All rights reserved. - */ - -#include -#include -#include -#include -#include - -#include - -#include "dp_clk_util.h" - -void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk) -{ - int i; - - for (i = num_clk - 1; i >= 0; i--) { - if (clk_arry[i].clk) - clk_put(clk_arry[i].clk); - clk_arry[i].clk = NULL; - } -} - -int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk) -{ - int i, rc = 0; - - for (i = 0; i < num_clk; i++) { - clk_arry[i].clk = clk_get(dev, clk_arry[i].clk_name); - rc = PTR_ERR_OR_ZERO(clk_arry[i].clk); - if (rc) { - DEV_ERR("%pS->%s: '%s' get failed. rc=%d\n", - __builtin_return_address(0), __func__, - clk_arry[i].clk_name, rc); - goto error; - } - } - - return rc; - -error: - for (i--; i >= 0; i--) { - if (clk_arry[i].clk) - clk_put(clk_arry[i].clk); - clk_arry[i].clk = NULL; - } - - return rc; -} - -int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable) -{ - int i, rc = 0; - - if (enable) { - for (i = 0; i < num_clk; i++) { - DEV_DBG("%pS->%s: enable '%s'\n", - __builtin_return_address(0), __func__, - clk_arry[i].clk_name); - rc = clk_prepare_enable(clk_arry[i].clk); - if (rc) - DEV_ERR("%pS->%s: %s en fail. rc=%d\n", - __builtin_return_address(0), - __func__, - clk_arry[i].clk_name, rc); - - if (rc && i) { - msm_dss_enable_clk(_arry[i - 1], - i - 1, false); - break; - } - } - } else { - for (i = num_clk - 1; i >= 0; i--) { - DEV_DBG("%pS->%s: disable '%s'\n", - __builtin_return_address(0), __func__, - clk_arry[i].clk_name); - - clk_disable_unprepare(clk_arry[i].clk); - } - } - - return rc; -} diff --git a/drivers/gpu/drm/msm/dp/dp_clk_util.h b/drivers/gpu/drm/msm/dp/dp_clk_util.h deleted file mode 100644 index c3d59b5017a9.. --- a/drivers/gpu/drm/msm/dp/dp_clk_util.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2012, 2017-2018, The Linux Foundation. All rights reserved. - */ - -#ifndef __DP_CLK_UTIL_H__ -#define __DP_CLK_UTIL_H__ - -#include -#include - -#define DEV_DBG(fmt, args...) pr_debug(fmt, ##args) -#define DEV_INFO(fmt, args...) pr_info(fmt, ##args) -#define DEV_WARN(fmt, args...) pr_warn(fmt, ##args) -#define DEV_ERR(fmt, args...) pr_err(fmt, ##args) - -struct dss_clk { - struct clk *clk; /* clk handle */ - char clk_name[32]; -}; - -struct dss_module_power { - unsigned int num_clk; - struct dss_clk *clk_config; -}; - -int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk); -void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk); -int msm_dss_enable_clk(struct dss_clk
[PATCH v5 4/5] drm/msm/dp: inline dp_power_clk_set_rate()
Inline the dp_power_clk_set_rate() function, replacing it with the call to msm_dss_enable_clk(). Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_power.c | 23 ++- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c index 6920d787e7aa..8d63a51cce7d 100644 --- a/drivers/gpu/drm/msm/dp/dp_power.c +++ b/drivers/gpu/drm/msm/dp/dp_power.c @@ -150,21 +150,6 @@ static int dp_power_clk_deinit(struct dp_power_private *power) return 0; } -static int dp_power_clk_set_rate(struct dp_power_private *power, - enum dp_pm_type module, bool enable) -{ - int rc = 0; - struct dss_module_power *mp = >parser->mp[module]; - - rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); - if (rc) { - DRM_ERROR("failed to %d clks, err: %d\n", enable, rc); - return rc; - } - - return 0; -} - int dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type) { DRM_DEBUG_DP("core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n", @@ -187,6 +172,7 @@ int dp_power_clk_enable(struct dp_power *dp_power, { int rc = 0; struct dp_power_private *power; + struct dss_module_power *mp; power = container_of(dp_power, struct dp_power_private, dp_power); @@ -214,9 +200,11 @@ int dp_power_clk_enable(struct dp_power *dp_power, } if ((pm_type == DP_CTRL_PM) && (!dp_power->core_clks_on)) { + mp = >parser->mp[DP_CORE_PM]; + DRM_DEBUG_DP("Enable core clks before link clks\n"); - rc = dp_power_clk_set_rate(power, DP_CORE_PM, enable); + rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); if (rc) { DRM_ERROR("fail to enable clks: %s. err=%d\n", dp_parser_pm_name(DP_CORE_PM), rc); @@ -226,7 +214,8 @@ int dp_power_clk_enable(struct dp_power *dp_power, } } - rc = dp_power_clk_set_rate(power, pm_type, enable); + mp = >parser->mp[pm_type]; + rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); if (rc) { DRM_ERROR("failed to '%s' clks for: %s. err=%d\n", enable ? "enable" : "disable", -- 2.34.1
[PATCH v5 3/5] drm/msm/dp: set stream_pixel rate directly
The only clock for which we set the rate is the "stream_pixel". Rather than storing the rate and then setting it by looping over all the clocks, set the clock rate directly. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_clk_util.c | 33 drivers/gpu/drm/msm/dp/dp_clk_util.h | 9 drivers/gpu/drm/msm/dp/dp_ctrl.c | 2 +- drivers/gpu/drm/msm/dp/dp_parser.c | 7 -- drivers/gpu/drm/msm/dp/dp_power.c| 10 - 5 files changed, 1 insertion(+), 60 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_clk_util.c b/drivers/gpu/drm/msm/dp/dp_clk_util.c index 44a4fc59ff31..85abed31c68b 100644 --- a/drivers/gpu/drm/msm/dp/dp_clk_util.c +++ b/drivers/gpu/drm/msm/dp/dp_clk_util.c @@ -51,39 +51,6 @@ int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk) return rc; } -int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk) -{ - int i, rc = 0; - - for (i = 0; i < num_clk; i++) { - if (clk_arry[i].clk) { - if (clk_arry[i].type != DSS_CLK_AHB) { - DEV_DBG("%pS->%s: '%s' rate %ld\n", - __builtin_return_address(0), __func__, - clk_arry[i].clk_name, - clk_arry[i].rate); - rc = clk_set_rate(clk_arry[i].clk, - clk_arry[i].rate); - if (rc) { - DEV_ERR("%pS->%s: %s failed. rc=%d\n", - __builtin_return_address(0), - __func__, - clk_arry[i].clk_name, rc); - break; - } - } - } else { - DEV_ERR("%pS->%s: '%s' is not available\n", - __builtin_return_address(0), __func__, - clk_arry[i].clk_name); - rc = -EPERM; - break; - } - } - - return rc; -} - int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable) { int i, rc = 0; diff --git a/drivers/gpu/drm/msm/dp/dp_clk_util.h b/drivers/gpu/drm/msm/dp/dp_clk_util.h index 067bf87f3d97..c3d59b5017a9 100644 --- a/drivers/gpu/drm/msm/dp/dp_clk_util.h +++ b/drivers/gpu/drm/msm/dp/dp_clk_util.h @@ -13,17 +13,9 @@ #define DEV_WARN(fmt, args...) pr_warn(fmt, ##args) #define DEV_ERR(fmt, args...) pr_err(fmt, ##args) -enum dss_clk_type { - DSS_CLK_AHB, /* no set rate. rate controlled through rpm */ - DSS_CLK_PCLK, -}; - struct dss_clk { struct clk *clk; /* clk handle */ char clk_name[32]; - enum dss_clk_type type; - unsigned long rate; - unsigned long max_rate; }; struct dss_module_power { @@ -33,6 +25,5 @@ struct dss_module_power { int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk); void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk); -int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk); int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable); #endif /* __DP_CLK_UTIL_H__ */ diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 07f6bf7e1acb..8e6361dedd77 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1315,7 +1315,7 @@ static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl, DRM_DEBUG_DP("setting rate=%lu on clk=%s\n", rate, name); if (num) - cfg->rate = rate; + clk_set_rate(cfg->clk, rate); else DRM_ERROR("%s clock doesn't exit to set rate %lu\n", name, rate); diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index a7acc23f742b..4f2d80bc0671 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -237,14 +237,12 @@ static int dp_parser_clock(struct dp_parser *parser) struct dss_clk *clk = _power->clk_config[core_clk_index]; strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name)); - clk->type = DSS_CLK_AHB; core_clk_index++; } else if (dp_parser_check_prefix("stream", clk_name) && stream_clk_index < stream_clk_count) { struct dss_clk *clk = _power->clk_config[stream_clk_index]; strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name)); - clk->type = DSS_CLK_PCLK;
[PATCH v5 1/5] drm/msm/dpu: simplify clocks handling
DPU driver contains code to parse clock items from device tree into special data struct and then enable/disable/set rate for the clocks using that data struct. However the DPU driver itself uses only parsing and enabling/disabling part (the rate setting is used by DP driver). Move this implementation to the DP driver (which actually uses rate setting) and replace hand-coded enable/disable/get loops in the DPU with the respective clk_bulk operations. Put operation is removed completely because, it is handled using devres instead. DP implementation is unchanged for now. Tested-by: Jessica Zhang # RB3 (sdm845) and RB5 (qrb5165) Reviewed-by: Jessica Zhang Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/Makefile | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 23 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h | 6 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 46 +++-- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 +- drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 26 +++ .../dpu1/dpu_io_util.c => dp/dp_clk_util.c} | 69 +-- .../dpu1/dpu_io_util.h => dp/dp_clk_util.h} | 8 +-- drivers/gpu/drm/msm/dp/dp_parser.h| 2 +- 9 files changed, 36 insertions(+), 150 deletions(-) rename drivers/gpu/drm/msm/{disp/dpu1/dpu_io_util.c => dp/dp_clk_util.c} (61%) rename drivers/gpu/drm/msm/{disp/dpu1/dpu_io_util.h => dp/dp_clk_util.h} (85%) diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 03ab55c37beb..a44abf0a7660 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -66,7 +66,6 @@ msm-y := \ disp/dpu1/dpu_hw_top.o \ disp/dpu1/dpu_hw_util.o \ disp/dpu1/dpu_hw_vbif.o \ - disp/dpu1/dpu_io_util.o \ disp/dpu1/dpu_kms.o \ disp/dpu1/dpu_mdss.o \ disp/dpu1/dpu_plane.o \ @@ -102,6 +101,7 @@ msm-$(CONFIG_DRM_MSM_GPU_STATE) += adreno/a6xx_gpu_state.o msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_catalog.o \ + dp/dp_clk_util.o \ dp/dp_ctrl.o \ dp/dp_display.o \ dp/dp_drm.o \ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 60fe06018581..a7492dd6ed65 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -284,17 +284,6 @@ void dpu_core_perf_crtc_release_bw(struct drm_crtc *crtc) } } -static int _dpu_core_perf_set_core_clk_rate(struct dpu_kms *kms, u64 rate) -{ - struct dss_clk *core_clk = kms->perf.core_clk; - - if (core_clk->max_rate && (rate > core_clk->max_rate)) - rate = core_clk->max_rate; - - core_clk->rate = rate; - return dev_pm_opp_set_rate(>pdev->dev, core_clk->rate); -} - static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms *kms) { u64 clk_rate = kms->perf.perf_tune.min_core_clk; @@ -306,7 +295,7 @@ static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms *kms) dpu_cstate = to_dpu_crtc_state(crtc->state); clk_rate = max(dpu_cstate->new_perf.core_clk_rate, clk_rate); - clk_rate = clk_round_rate(kms->perf.core_clk->clk, + clk_rate = clk_round_rate(kms->perf.core_clk, clk_rate); } } @@ -405,10 +394,10 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc, trace_dpu_core_perf_update_clk(kms->dev, stop_req, clk_rate); - ret = _dpu_core_perf_set_core_clk_rate(kms, clk_rate); + clk_rate = min(clk_rate, kms->perf.max_core_clk_rate); + ret = dev_pm_opp_set_rate(>pdev->dev, clk_rate); if (ret) { - DPU_ERROR("failed to set %s clock rate %llu\n", - kms->perf.core_clk->clk_name, clk_rate); + DPU_ERROR("failed to set core clock rate %llu\n", clk_rate); return ret; } @@ -529,13 +518,13 @@ void dpu_core_perf_destroy(struct dpu_core_perf *perf) int dpu_core_perf_init(struct dpu_core_perf *perf, struct drm_device *dev, struct dpu_mdss_cfg *catalog, - struct dss_clk *core_clk) + struct clk *core_clk) { perf->dev = dev; perf->catalog = catalog; perf->core_clk = core_clk; - perf->max_core_clk_rate = core_clk->max_rate; + perf->max_core_clk_rate = clk_get_rate(core_clk); if (!perf->max_core_clk_rate) { DPU_DEBUG("optional max core clk rate, use default\n"); perf->max_core_clk_rate = DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h index
[PATCH v5 2/5] drm/msm/dp: "inline" dp_ctrl_set_clock_rate("ctrl_link")
"ctrl_link" is the clock from DP_CTRL_PM module. The result of setting the rate for it would be a call to dev_pm_opp_set_rate(). Instead of saving the rate inside struct dss_module_power, call the devm_pm_opp_set_rate() directly. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 7 +-- drivers/gpu/drm/msm/dp/dp_power.c | 33 +-- 2 files changed, 6 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index c724cb0bde9d..07f6bf7e1acb 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1332,12 +1332,11 @@ static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl) opts_dp->lanes = ctrl->link->link_params.num_lanes; opts_dp->link_rate = ctrl->link->link_params.rate / 100; opts_dp->ssc = drm_dp_max_downspread(dpcd); - dp_ctrl_set_clock_rate(ctrl, DP_CTRL_PM, "ctrl_link", - ctrl->link->link_params.rate * 1000); phy_configure(phy, _io->phy_opts); phy_power_on(phy); + dev_pm_opp_set_rate(ctrl->dev, ctrl->link->link_params.rate * 1000); ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, true); if (ret) DRM_ERROR("Unable to start link clocks. ret=%d\n", ret); @@ -1451,6 +1450,7 @@ static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl) * link clock might have been adjusted as part of the * link maintenance. */ + dev_pm_opp_set_rate(ctrl->dev, 0); ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false); if (ret) { DRM_ERROR("Failed to disable clocks. ret=%d\n", ret); @@ -1482,6 +1482,7 @@ static int dp_ctrl_deinitialize_mainlink(struct dp_ctrl_private *ctrl) dp_catalog_ctrl_reset(ctrl->catalog); + dev_pm_opp_set_rate(ctrl->dev, 0); ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false); if (ret) { DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret); @@ -1887,6 +1888,7 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl) } } + dev_pm_opp_set_rate(ctrl->dev, 0); ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false); if (ret) { DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret); @@ -1942,6 +1944,7 @@ int dp_ctrl_off(struct dp_ctrl *dp_ctrl) if (ret) DRM_ERROR("Failed to disable pixel clocks. ret=%d\n", ret); + dev_pm_opp_set_rate(ctrl->dev, 0); ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false); if (ret) { DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret); diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c index b48b45e92bfa..893a57dd97d9 100644 --- a/drivers/gpu/drm/msm/dp/dp_power.c +++ b/drivers/gpu/drm/msm/dp/dp_power.c @@ -150,44 +150,13 @@ static int dp_power_clk_deinit(struct dp_power_private *power) return 0; } -static int dp_power_clk_set_link_rate(struct dp_power_private *power, - struct dss_clk *clk_arry, int num_clk, int enable) -{ - u32 rate; - int i, rc = 0; - - for (i = 0; i < num_clk; i++) { - if (clk_arry[i].clk) { - if (clk_arry[i].type == DSS_CLK_PCLK) { - if (enable) - rate = clk_arry[i].rate; - else - rate = 0; - - rc = dev_pm_opp_set_rate(power->dev, rate); - if (rc) - break; - } - - } - } - return rc; -} - static int dp_power_clk_set_rate(struct dp_power_private *power, enum dp_pm_type module, bool enable) { int rc = 0; struct dss_module_power *mp = >parser->mp[module]; - if (module == DP_CTRL_PM) { - rc = dp_power_clk_set_link_rate(power, mp->clk_config, mp->num_clk, enable); - if (rc) { - DRM_ERROR("failed to set link clks rate\n"); - return rc; - } - } else { - + if (module != DP_CTRL_PM) { if (enable) { rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk); if (rc) { -- 2.34.1
[PATCH v5 0/5] drm/msm: rework clock handling
msm_dss_clk_*() functions significantly duplicate clk_bulk_* family of functions. Drop custom code and use bulk clocks directly. This also removes dependency of DP driver on the DPU driver internals. Note that DP changes were compile-only tested. Changes since v4: - Use size_t for num_clocks in dpu_kms/dpu_mdss - Use min() in dpu_core_perf_crtc_update() - Drop overcomplicated clock rate setting wrappers inside DP code. We were setting the opp for one clock and setting a rate for a single clock! Call dev_pm_opp_set_rate() and clk_set_rate() directly. Changes since v3: - Switched to devm_clk_bulk_get_all() per Stephen's suggestion. - Removed a call to of_clk_set_defaults() (per Stephen's suggestion again). It duplicates a call in platform_probe(). - Split the first patch (moving helpers to msm_io_utils.c), it's unused now. Changes since v2: - Retain conditional code/prints in DP code to ease debugging - Rebase on top of msm-next and [1] - Split helper functions to msm_io_utils.c as suggested by Jessica Changes since v1: - Rebase on top of current tree to fix conflicts Dmitry Baryshkov (5): drm/msm/dpu: simplify clocks handling drm/msm/dp: "inline" dp_ctrl_set_clock_rate("ctrl_link") drm/msm/dp: set stream_pixel rate directly drm/msm/dp: inline dp_power_clk_set_rate() drm/msm/dp: rewrite dss_module_power to use bulk clock functions drivers/gpu/drm/msm/Makefile | 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 23 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h | 6 +- drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c | 187 -- drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h | 40 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 46 ++--- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 +- drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 26 +-- drivers/gpu/drm/msm/dp/dp_ctrl.c | 13 +- drivers/gpu/drm/msm/dp/dp_parser.c| 43 ++-- drivers/gpu/drm/msm/dp/dp_parser.h| 6 +- drivers/gpu/drm/msm/dp/dp_power.c | 105 ++ 12 files changed, 74 insertions(+), 426 deletions(-) delete mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c delete mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h -- 2.34.1
[PATCH v3 5/6] drm/msm/dpu: remove struct dpu_encoder_irq
Remove additional indirection: specify IRQ callbacks and IRQ indices directly rather than through the pointer in the irq structure. For each IRQ we have a constant IRQ callback. This change simplifies code review as the reader no longer needs to remember which function is called. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 28 +++ .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 21 +- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 73 +++ .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 42 --- 4 files changed, 58 insertions(+), 106 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index dbcbf96cf8eb..83b6715820fa 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -261,9 +261,10 @@ static int dpu_encoder_helper_wait_event_timeout(int32_t drm_id, int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, enum dpu_intr_idx intr_idx, + void (*func)(void *arg, int irq_idx), struct dpu_encoder_wait_info *wait_info) { - struct dpu_encoder_irq *irq; + int irq; u32 irq_status; int ret; @@ -271,7 +272,7 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, DPU_ERROR("invalid params\n"); return -EINVAL; } - irq = _enc->irq[intr_idx]; + irq = phys_enc->irq[intr_idx]; /* note: do master / slave checking outside */ @@ -279,53 +280,52 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, if (phys_enc->enable_state == DPU_ENC_DISABLED) { DRM_ERROR("encoder is disabled id=%u, intr=%d, irq=%d\n", DRMID(phys_enc->parent), intr_idx, - irq->irq_idx); + irq); return -EWOULDBLOCK; } - if (irq->irq_idx < 0) { - DRM_DEBUG_KMS("skip irq wait id=%u, intr=%d, irq=%s\n", - DRMID(phys_enc->parent), intr_idx, - irq->name); + if (irq < 0) { + DRM_DEBUG_KMS("skip irq wait id=%u, intr=%d\n", + DRMID(phys_enc->parent), intr_idx); return 0; } DRM_DEBUG_KMS("id=%u, intr=%d, irq=%d, pp=%d, pending_cnt=%d\n", DRMID(phys_enc->parent), intr_idx, - irq->irq_idx, phys_enc->hw_pp->idx - PINGPONG_0, + irq, 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, wait_info); if (ret <= 0) { - irq_status = dpu_core_irq_read(phys_enc->dpu_kms, irq->irq_idx); + irq_status = dpu_core_irq_read(phys_enc->dpu_kms, irq); if (irq_status) { unsigned long flags; DRM_DEBUG_KMS("irq not triggered id=%u, intr=%d, irq=%d, pp=%d, atomic_cnt=%d\n", DRMID(phys_enc->parent), intr_idx, - irq->irq_idx, + irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); local_irq_save(flags); - irq->func(phys_enc, irq->irq_idx); + func(phys_enc, irq); local_irq_restore(flags); ret = 0; } else { ret = -ETIMEDOUT; DRM_DEBUG_KMS("irq timeout id=%u, intr=%d, irq=%d, pp=%d, atomic_cnt=%d\n", DRMID(phys_enc->parent), intr_idx, - irq->irq_idx, + irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); } } else { ret = 0; trace_dpu_enc_irq_wait_success(DRMID(phys_enc->parent), - intr_idx, irq->irq_idx, + intr_idx, irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); } 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 ff2218155b44..803fd6f25da1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -162,21 +162,6 @@ enum dpu_intr_idx {
[PATCH v3 6/6] drm/msm/dpu: pass irq to dpu_encoder_helper_wait_for_irq()
Pass IRQ number directly rather than passing an index in the dpu_encoder's irq table. Reviewed-by: Stephen Boyd Reviewed-by: Abhinav Kumar Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 29 +-- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 4 +-- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 9 -- .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 3 +- drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 12 5 files changed, 29 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 83b6715820fa..4c9e7c4fa14b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -260,38 +260,35 @@ 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, void (*func)(void *arg, int irq_idx), struct dpu_encoder_wait_info *wait_info) { - int irq; u32 irq_status; int ret; - if (!wait_info || intr_idx >= INTR_IDX_MAX) { + if (!wait_info) { DPU_ERROR("invalid params\n"); return -EINVAL; } - irq = phys_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\n", - DRMID(phys_enc->parent), intr_idx, + DRM_ERROR("encoder is disabled id=%u, callback=%ps, irq=%d\n", + DRMID(phys_enc->parent), func, irq); return -EWOULDBLOCK; } if (irq < 0) { - DRM_DEBUG_KMS("skip irq wait id=%u, intr=%d\n", - DRMID(phys_enc->parent), intr_idx); + DRM_DEBUG_KMS("skip irq wait id=%u, callback=%ps\n", + DRMID(phys_enc->parent), func); return 0; } - DRM_DEBUG_KMS("id=%u, intr=%d, irq=%d, pp=%d, pending_cnt=%d\n", - DRMID(phys_enc->parent), intr_idx, + DRM_DEBUG_KMS("id=%u, callback=%ps, irq=%d, pp=%d, pending_cnt=%d\n", + DRMID(phys_enc->parent), func, irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); @@ -305,8 +302,8 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, if (irq_status) { unsigned long flags; - DRM_DEBUG_KMS("irq not triggered id=%u, intr=%d, irq=%d, pp=%d, atomic_cnt=%d\n", - DRMID(phys_enc->parent), intr_idx, + DRM_DEBUG_KMS("irq not triggered id=%u, callback=%ps, irq=%d, pp=%d, atomic_cnt=%d\n", + DRMID(phys_enc->parent), func, irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); @@ -316,8 +313,8 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, ret = 0; } else { ret = -ETIMEDOUT; - DRM_DEBUG_KMS("irq timeout id=%u, intr=%d, irq=%d, pp=%d, atomic_cnt=%d\n", - DRMID(phys_enc->parent), intr_idx, + DRM_DEBUG_KMS("irq timeout id=%u, callback=%ps, irq=%d, pp=%d, atomic_cnt=%d\n", + DRMID(phys_enc->parent), func, irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); @@ -325,7 +322,7 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, } else { ret = 0; trace_dpu_enc_irq_wait_success(DRMID(phys_enc->parent), - intr_idx, irq, + func, irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); } 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 803fd6f25da1..9843acdc33bd 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -341,13 +341,13 @@ void dpu_encoder_helper_report_irq_timeout(struct dpu_encoder_phys *phys_enc, * dpu_encoder_helper_wait_for_irq - utility to wait on an
[PATCH v3 1/6] drm/msm/dpu: remove extra wrappers around dpu_core_irq
Remove extra dpu_irq_* wrappers from dpu_kms.c, merge them directly into dpu_core_irq_* functions. Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov --- 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 90ae6c9ccc95..7023ccb79814 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 a77a5eaa78ad..71882d3fe705 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -162,8 +162,9 @@ static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, int irq_idx) cb->func(cb->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; @@ -569,8 +570,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); @@ -589,8 +591,9 @@ void dpu_core_irq_preinstall(struct dpu_kms *dpu_kms) } } -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 47fe11a84a77..364bd4e60fba 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -841,20 +841,6 @@ static void dpu_kms_destroy(struct msm_kms *kms) msm_kms_destroy(_kms->base); } -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; @@ -874,13 +860,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; @@ -933,10 +912,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, -- 2.34.1
[PATCH v3 3/6] drm/msm/dpu: allow just single IRQ callback
DPU interrupts code allows multiple callbacks per interrut. In reality 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. Reported-by: kernel test robot Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h | 16 +- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 7 +- .../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 | 140 ++ .../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 | 26 ++-- 9 files changed, 84 insertions(+), 147 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 6dce5d89f817..b5b6e7031fb9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h @@ -44,10 +44,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. @@ -55,25 +53,21 @@ 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. * @return:0 for success registering callback, otherwise failure * * This function supports registration of multiple callbacks for each interrupt. */ int dpu_core_irq_unregister_callback( struct dpu_kms *dpu_kms, - int irq_idx, - struct dpu_irq_callback *irq_cb); + int irq_idx); /** * 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 5576b8a3e6ee..17ca149e7dcd 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -311,7 +311,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", @@ -383,8 +383,7 @@ int dpu_encoder_helper_unregister_irq(struct dpu_encoder_phys *phys_enc, return 0; } - ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, irq->irq_idx, - >cb); + ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, irq->irq_idx); if (ret) { DRM_ERROR("unreg cb fail id=%u, intr=%d, irq=%d ret=%d", DRMID(phys_enc->parent), intr_idx, 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 e7270eb6b84b..80d87871fd94 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -174,7 +174,7 @@ struct dpu_encoder_irq { const char *name; enum dpu_intr_idx
[PATCH v3 4/6] drm/msm/dpu: get rid of dpu_encoder_helper_(un)register_irq
Get rid of dpu_encoder_helper_register_irq/unregister_irq helpers, call dpu_core_register/unregister_callback directly, without surrounding them with helpers. Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 63 --- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 18 -- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 34 ++ .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 18 -- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 4 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 29 +++-- 6 files changed, 48 insertions(+), 118 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 17ca149e7dcd..dbcbf96cf8eb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -333,69 +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); - 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_vsync_count(struct drm_encoder *drm_enc) { struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_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 a0652bdcf59b..ca7d557312ff 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,8 @@ 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); +
[PATCH v3 2/6] drm/msm/dpu: remove always-true argument of dpu_core_irq_read()
The argument clear of the function dpu_core_irq_read() is always true. Remove it. Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h | 4 +--- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 3 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 4 ++-- 3 files changed, 4 insertions(+), 7 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 7023ccb79814..6dce5d89f817 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h @@ -33,13 +33,11 @@ irqreturn_t dpu_core_irq(struct msm_kms *kms); * dpu_core_irq_read - IRQ helper function for reading IRQ status * @dpu_kms: DPU handle * @irq_idx: irq index - * @clear: True to clear the irq after read * @return:non-zero if irq detected; otherwise no irq detected */ u32 dpu_core_irq_read( struct dpu_kms *dpu_kms, - int irq_idx, - bool clear); + int irq_idx); /** * dpu_core_irq_register_callback - For registering callback function on IRQ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 1e648db439f9..5576b8a3e6ee 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -301,8 +301,7 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, wait_info); if (ret <= 0) { - irq_status = dpu_core_irq_read(phys_enc->dpu_kms, - irq->irq_idx, true); + irq_status = dpu_core_irq_read(phys_enc->dpu_kms, irq->irq_idx); if (irq_status) { unsigned long flags; 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 71882d3fe705..85404c9ab4e1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -357,7 +357,7 @@ static void dpu_disable_all_irqs(struct dpu_kms *dpu_kms) wmb(); } -u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx, bool clear) +u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx) { struct dpu_hw_intr *intr = dpu_kms->hw_intr; int reg_idx; @@ -384,7 +384,7 @@ u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx, bool clear) intr_status = DPU_REG_READ(>hw, dpu_intr_set[reg_idx].status_off) & DPU_IRQ_MASK(irq_idx); - if (intr_status && clear) + if (intr_status) DPU_REG_WRITE(>hw, dpu_intr_set[reg_idx].clr_off, intr_status); -- 2.34.1
[PATCH v3 0/6] drm/msm/dpu: simplify IRQ helpers
This is the second part of https://patchwork.freedesktop.org/series/91631/ reworked and cleaned up. Changes since v1: - Fix warning ins dpu_trace.h related to dpu_core_irq_unregister_callback event Changes since v1: - Use ARRAY_SIZE() rather INTR_IDX_MAX when clearing irq arrays. Changes since the original pull request: - Split applied patches - Add unlikely and WARN_ON in dpu_core_irq_register_callback() - Remove extra checks in dpu_core_irq_unregister_callback() - Remove unused arguments of dpu_core_irq_unregister_callback() - Clean the cb and arg in dpu_core_irq_unregister_callback() - Split the last patch. Leave enum dpu_intr_idx intact. Pass irq index, callback and data directly to dpu_encoder helpers. Dmitry Baryshkov (6): drm/msm/dpu: remove extra wrappers around dpu_core_irq drm/msm/dpu: remove always-true argument of dpu_core_irq_read() drm/msm/dpu: allow just single IRQ callback drm/msm/dpu: get rid of dpu_encoder_helper_(un)register_irq drm/msm/dpu: remove struct dpu_encoder_irq drm/msm/dpu: pass irq to dpu_encoder_helper_wait_for_irq() drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h | 32 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 112 +++-- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 43 + .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 92 +- .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 51 +++--- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 157 +++--- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 12 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 27 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 12 -- drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 67 10 files changed, 202 insertions(+), 403 deletions(-) -- 2.34.1
Re: [REPOST PATCH v4 04/13] drm/msm/disp/dpu1: Add support for DSC in pingpong block
On 16-02-22, 11:49, Abhinav Kumar wrote: > > > On 2/10/2022 2:34 AM, Vinod Koul wrote: > > In SDM845, DSC can be enabled by writing to pingpong block registers, so > > add support for DSC in hw_pp > > > > Reviewed-by: Abhinav Kumar > > For the sake of uniformity, please use > > Reviewed-by: Abhinav Kumar This one has been carry fwd from few versions back :) will update everywhere... -- ~Vinod
Re: [REPOST PATCH v4 03/13] drm/msm/disp/dpu1: Add support for DSC
On 16-02-22, 22:46, Dmitry Baryshkov wrote: > On 16/02/2022 21:57, Abhinav Kumar wrote: > > > > > > On 2/10/2022 2:34 AM, Vinod Koul wrote: > > > Display Stream Compression (DSC) is one of the hw blocks in dpu, so add > > > support by adding hw blocks for DSC > > > > > > Reviewed-by: Dmitry Baryshkov > > > Signed-off-by: Vinod Koul > > > > Somehow second patch of this series is not showing up on patchwork in > > your REPOST. > > > > It jumps from 1 to 3. > > patch 2: https://patchwork.freedesktop.org/patch/473356/?series=99959=1 yeah it seems to be there.. As well os arm-msm and dri-devel on k.org pwProblem with QC delivery...? -- ~Vinod
[PATCH v2 5/6] drm/msm/dpu: remove struct dpu_encoder_irq
Remove additional indirection: specify IRQ callbacks and IRQ indices directly rather than through the pointer in the irq structure. For each IRQ we have a constant IRQ callback. This change simplifies code review as the reader no longer needs to remember which function is called. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 28 +++ .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 21 +- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 73 +++ .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 42 --- 4 files changed, 58 insertions(+), 106 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index dbcbf96cf8eb..83b6715820fa 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -261,9 +261,10 @@ static int dpu_encoder_helper_wait_event_timeout(int32_t drm_id, int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, enum dpu_intr_idx intr_idx, + void (*func)(void *arg, int irq_idx), struct dpu_encoder_wait_info *wait_info) { - struct dpu_encoder_irq *irq; + int irq; u32 irq_status; int ret; @@ -271,7 +272,7 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, DPU_ERROR("invalid params\n"); return -EINVAL; } - irq = _enc->irq[intr_idx]; + irq = phys_enc->irq[intr_idx]; /* note: do master / slave checking outside */ @@ -279,53 +280,52 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, if (phys_enc->enable_state == DPU_ENC_DISABLED) { DRM_ERROR("encoder is disabled id=%u, intr=%d, irq=%d\n", DRMID(phys_enc->parent), intr_idx, - irq->irq_idx); + irq); return -EWOULDBLOCK; } - if (irq->irq_idx < 0) { - DRM_DEBUG_KMS("skip irq wait id=%u, intr=%d, irq=%s\n", - DRMID(phys_enc->parent), intr_idx, - irq->name); + if (irq < 0) { + DRM_DEBUG_KMS("skip irq wait id=%u, intr=%d\n", + DRMID(phys_enc->parent), intr_idx); return 0; } DRM_DEBUG_KMS("id=%u, intr=%d, irq=%d, pp=%d, pending_cnt=%d\n", DRMID(phys_enc->parent), intr_idx, - irq->irq_idx, phys_enc->hw_pp->idx - PINGPONG_0, + irq, 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, wait_info); if (ret <= 0) { - irq_status = dpu_core_irq_read(phys_enc->dpu_kms, irq->irq_idx); + irq_status = dpu_core_irq_read(phys_enc->dpu_kms, irq); if (irq_status) { unsigned long flags; DRM_DEBUG_KMS("irq not triggered id=%u, intr=%d, irq=%d, pp=%d, atomic_cnt=%d\n", DRMID(phys_enc->parent), intr_idx, - irq->irq_idx, + irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); local_irq_save(flags); - irq->func(phys_enc, irq->irq_idx); + func(phys_enc, irq); local_irq_restore(flags); ret = 0; } else { ret = -ETIMEDOUT; DRM_DEBUG_KMS("irq timeout id=%u, intr=%d, irq=%d, pp=%d, atomic_cnt=%d\n", DRMID(phys_enc->parent), intr_idx, - irq->irq_idx, + irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); } } else { ret = 0; trace_dpu_enc_irq_wait_success(DRMID(phys_enc->parent), - intr_idx, irq->irq_idx, + intr_idx, irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); } 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 ff2218155b44..803fd6f25da1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -162,21 +162,6 @@ enum dpu_intr_idx {
[PATCH v2 6/6] drm/msm/dpu: pass irq to dpu_encoder_helper_wait_for_irq()
Pass IRQ number directly rather than passing an index in the dpu_encoder's irq table. Reviewed-by: Stephen Boyd Reviewed-by: Abhinav Kumar Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 29 +-- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 4 +-- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 9 -- .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 3 +- drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 12 5 files changed, 29 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 83b6715820fa..4c9e7c4fa14b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -260,38 +260,35 @@ 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, void (*func)(void *arg, int irq_idx), struct dpu_encoder_wait_info *wait_info) { - int irq; u32 irq_status; int ret; - if (!wait_info || intr_idx >= INTR_IDX_MAX) { + if (!wait_info) { DPU_ERROR("invalid params\n"); return -EINVAL; } - irq = phys_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\n", - DRMID(phys_enc->parent), intr_idx, + DRM_ERROR("encoder is disabled id=%u, callback=%ps, irq=%d\n", + DRMID(phys_enc->parent), func, irq); return -EWOULDBLOCK; } if (irq < 0) { - DRM_DEBUG_KMS("skip irq wait id=%u, intr=%d\n", - DRMID(phys_enc->parent), intr_idx); + DRM_DEBUG_KMS("skip irq wait id=%u, callback=%ps\n", + DRMID(phys_enc->parent), func); return 0; } - DRM_DEBUG_KMS("id=%u, intr=%d, irq=%d, pp=%d, pending_cnt=%d\n", - DRMID(phys_enc->parent), intr_idx, + DRM_DEBUG_KMS("id=%u, callback=%ps, irq=%d, pp=%d, pending_cnt=%d\n", + DRMID(phys_enc->parent), func, irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); @@ -305,8 +302,8 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, if (irq_status) { unsigned long flags; - DRM_DEBUG_KMS("irq not triggered id=%u, intr=%d, irq=%d, pp=%d, atomic_cnt=%d\n", - DRMID(phys_enc->parent), intr_idx, + DRM_DEBUG_KMS("irq not triggered id=%u, callback=%ps, irq=%d, pp=%d, atomic_cnt=%d\n", + DRMID(phys_enc->parent), func, irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); @@ -316,8 +313,8 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, ret = 0; } else { ret = -ETIMEDOUT; - DRM_DEBUG_KMS("irq timeout id=%u, intr=%d, irq=%d, pp=%d, atomic_cnt=%d\n", - DRMID(phys_enc->parent), intr_idx, + DRM_DEBUG_KMS("irq timeout id=%u, callback=%ps, irq=%d, pp=%d, atomic_cnt=%d\n", + DRMID(phys_enc->parent), func, irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); @@ -325,7 +322,7 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, } else { ret = 0; trace_dpu_enc_irq_wait_success(DRMID(phys_enc->parent), - intr_idx, irq, + func, irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); } 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 803fd6f25da1..9843acdc33bd 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -341,13 +341,13 @@ void dpu_encoder_helper_report_irq_timeout(struct dpu_encoder_phys *phys_enc, * dpu_encoder_helper_wait_for_irq - utility to wait on an
[PATCH v2 1/6] drm/msm/dpu: remove extra wrappers around dpu_core_irq
Remove extra dpu_irq_* wrappers from dpu_kms.c, merge them directly into dpu_core_irq_* functions. Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov --- 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 90ae6c9ccc95..7023ccb79814 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 a77a5eaa78ad..71882d3fe705 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -162,8 +162,9 @@ static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, int irq_idx) cb->func(cb->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; @@ -569,8 +570,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); @@ -589,8 +591,9 @@ void dpu_core_irq_preinstall(struct dpu_kms *dpu_kms) } } -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 47fe11a84a77..364bd4e60fba 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -841,20 +841,6 @@ static void dpu_kms_destroy(struct msm_kms *kms) msm_kms_destroy(_kms->base); } -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; @@ -874,13 +860,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; @@ -933,10 +912,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, -- 2.34.1
[PATCH v2 3/6] drm/msm/dpu: allow just single IRQ callback
DPU interrupts code allows multiple callbacks per interrut. In reality 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. Reported-by: kernel test robot Reported-by: kernel test robot Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h | 16 +- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 7 +- .../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 | 140 ++ .../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 | 12 +- 9 files changed, 75 insertions(+), 142 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 6dce5d89f817..b5b6e7031fb9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h @@ -44,10 +44,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. @@ -55,25 +53,21 @@ 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. * @return:0 for success registering callback, otherwise failure * * This function supports registration of multiple callbacks for each interrupt. */ int dpu_core_irq_unregister_callback( struct dpu_kms *dpu_kms, - int irq_idx, - struct dpu_irq_callback *irq_cb); + int irq_idx); /** * 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 5576b8a3e6ee..17ca149e7dcd 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -311,7 +311,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", @@ -383,8 +383,7 @@ int dpu_encoder_helper_unregister_irq(struct dpu_encoder_phys *phys_enc, return 0; } - ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, irq->irq_idx, - >cb); + ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, irq->irq_idx); if (ret) { DRM_ERROR("unreg cb fail id=%u, intr=%d, irq=%d ret=%d", DRMID(phys_enc->parent), intr_idx, 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 e7270eb6b84b..80d87871fd94 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -174,7 +174,7 @@ struct dpu_encoder_irq { const char
[PATCH v2 2/6] drm/msm/dpu: remove always-true argument of dpu_core_irq_read()
The argument clear of the function dpu_core_irq_read() is always true. Remove it. Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h | 4 +--- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 3 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 4 ++-- 3 files changed, 4 insertions(+), 7 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 7023ccb79814..6dce5d89f817 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h @@ -33,13 +33,11 @@ irqreturn_t dpu_core_irq(struct msm_kms *kms); * dpu_core_irq_read - IRQ helper function for reading IRQ status * @dpu_kms: DPU handle * @irq_idx: irq index - * @clear: True to clear the irq after read * @return:non-zero if irq detected; otherwise no irq detected */ u32 dpu_core_irq_read( struct dpu_kms *dpu_kms, - int irq_idx, - bool clear); + int irq_idx); /** * dpu_core_irq_register_callback - For registering callback function on IRQ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 1e648db439f9..5576b8a3e6ee 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -301,8 +301,7 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, wait_info); if (ret <= 0) { - irq_status = dpu_core_irq_read(phys_enc->dpu_kms, - irq->irq_idx, true); + irq_status = dpu_core_irq_read(phys_enc->dpu_kms, irq->irq_idx); if (irq_status) { unsigned long flags; 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 71882d3fe705..85404c9ab4e1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -357,7 +357,7 @@ static void dpu_disable_all_irqs(struct dpu_kms *dpu_kms) wmb(); } -u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx, bool clear) +u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx) { struct dpu_hw_intr *intr = dpu_kms->hw_intr; int reg_idx; @@ -384,7 +384,7 @@ u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx, bool clear) intr_status = DPU_REG_READ(>hw, dpu_intr_set[reg_idx].status_off) & DPU_IRQ_MASK(irq_idx); - if (intr_status && clear) + if (intr_status) DPU_REG_WRITE(>hw, dpu_intr_set[reg_idx].clr_off, intr_status); -- 2.34.1
[PATCH v2 4/6] drm/msm/dpu: get rid of dpu_encoder_helper_(un)register_irq
Get rid of dpu_encoder_helper_register_irq/unregister_irq helpers, call dpu_core_register/unregister_callback directly, without surrounding them with helpers. Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 63 --- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 18 -- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 34 ++ .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 18 -- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 4 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 29 +++-- 6 files changed, 48 insertions(+), 118 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 17ca149e7dcd..dbcbf96cf8eb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -333,69 +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); - 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_vsync_count(struct drm_encoder *drm_enc) { struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_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 a0652bdcf59b..ca7d557312ff 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,8 @@ 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); +
[PATCH v2 0/6] drm/msm/dpu: simplify IRQ helpers
This is the second part of https://patchwork.freedesktop.org/series/91631/ reworked and cleaned up. Changes since v1: - Use ARRAY_SIZE() rather INTR_IDX_MAX when clearing irq arrays. Changes since the original pull request: - Split applied patches - Add unlikely and WARN_ON in dpu_core_irq_register_callback() - Remove extra checks in dpu_core_irq_unregister_callback() - Remove unused arguments of dpu_core_irq_unregister_callback() - Clean the cb and arg in dpu_core_irq_unregister_callback() - Split the last patch. Leave enum dpu_intr_idx intact. Pass irq index, callback and data directly to dpu_encoder helpers. Dmitry Baryshkov (6): drm/msm/dpu: remove extra wrappers around dpu_core_irq drm/msm/dpu: remove always-true argument of dpu_core_irq_read() drm/msm/dpu: allow just single IRQ callback drm/msm/dpu: get rid of dpu_encoder_helper_(un)register_irq drm/msm/dpu: remove struct dpu_encoder_irq drm/msm/dpu: pass irq to dpu_encoder_helper_wait_for_irq() drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h | 32 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 112 +++-- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 43 + .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 92 +- .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 51 +++--- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 157 +++--- .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 12 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 27 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 12 -- drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 53 +++--- 10 files changed, 193 insertions(+), 398 deletions(-) -- 2.34.1
Re: [PATCH 5/6] drm/msm/dpu: remove struct dpu_encoder_irq
On 16/02/2022 04:56, Abhinav Kumar wrote: On 2/1/2022 7:10 AM, Dmitry Baryshkov wrote: Remove additional indirection: specify IRQ callbacks and IRQ indices directly rather than through the pointer in the irq structure. For each IRQ we have a constant IRQ callback. This change simplifies code review as the reader no longer needs to remember which function is called. Signed-off-by: Dmitry Baryshkov The change itself is fine as it will help to reduce yet another struct struct dpu_encoder_irq. One suggestion I can think of is, this also gets rid of the "name" member which can be useful for debugging. Do you think we can add a helper dpu_encoder_irq_idx_to_name(int idx) Which will just translate this enum to the relevant string and add that to the prints which were previously using the "name" member? I gave this idea a thought. Such function would seem to be usefull in dpu_encoder_helper_wait_for_irq(). However the next patch removes the intr_idx argument and replaces it with irq and *func. And, as you can see, after the next patch the function already uses func symbol instead of intr_idx to ease debugging. As the used callbacks are static, this gives the same information. 156 enum dpu_intr_idx { 157 INTR_IDX_VSYNC, 158 INTR_IDX_PINGPONG, 159 INTR_IDX_UNDERRUN, 160 INTR_IDX_CTL_START, 161 INTR_IDX_RDPTR, 162 INTR_IDX_MAX, 163 }; Let me know if you think this will be useful. --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 28 +++ .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 21 +- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 73 +++ .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 42 --- 4 files changed, 58 insertions(+), 106 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index dbcbf96cf8eb..83b6715820fa 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -261,9 +261,10 @@ static int dpu_encoder_helper_wait_event_timeout(int32_t drm_id, int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, enum dpu_intr_idx intr_idx, + void (*func)(void *arg, int irq_idx), struct dpu_encoder_wait_info *wait_info) { - struct dpu_encoder_irq *irq; + int irq; u32 irq_status; int ret; @@ -271,7 +272,7 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, DPU_ERROR("invalid params\n"); return -EINVAL; } - irq = _enc->irq[intr_idx]; + irq = phys_enc->irq[intr_idx]; /* note: do master / slave checking outside */ @@ -279,53 +280,52 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, if (phys_enc->enable_state == DPU_ENC_DISABLED) { DRM_ERROR("encoder is disabled id=%u, intr=%d, irq=%d\n", DRMID(phys_enc->parent), intr_idx, - irq->irq_idx); + irq); return -EWOULDBLOCK; } - if (irq->irq_idx < 0) { - DRM_DEBUG_KMS("skip irq wait id=%u, intr=%d, irq=%s\n", - DRMID(phys_enc->parent), intr_idx, - irq->name); + if (irq < 0) { + DRM_DEBUG_KMS("skip irq wait id=%u, intr=%d\n", + DRMID(phys_enc->parent), intr_idx); return 0; } DRM_DEBUG_KMS("id=%u, intr=%d, irq=%d, pp=%d, pending_cnt=%d\n", DRMID(phys_enc->parent), intr_idx, - irq->irq_idx, phys_enc->hw_pp->idx - PINGPONG_0, + irq, 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, wait_info); if (ret <= 0) { - irq_status = dpu_core_irq_read(phys_enc->dpu_kms, irq->irq_idx); + irq_status = dpu_core_irq_read(phys_enc->dpu_kms, irq); if (irq_status) { unsigned long flags; DRM_DEBUG_KMS("irq not triggered id=%u, intr=%d, irq=%d, pp=%d, atomic_cnt=%d\n", DRMID(phys_enc->parent), intr_idx, - irq->irq_idx, + irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); local_irq_save(flags); - irq->func(phys_enc, irq->irq_idx); + func(phys_enc, irq); local_irq_restore(flags); ret = 0; } else { ret = -ETIMEDOUT; DRM_DEBUG_KMS("irq timeout id=%u, intr=%d, irq=%d, pp=%d, atomic_cnt=%d\n", DRMID(phys_enc->parent), intr_idx, - irq->irq_idx, + irq, phys_enc->hw_pp->idx - PINGPONG_0, atomic_read(wait_info->atomic_cnt)); } } else {
[PATCH v2 1/7] drm/msm/dpu: fix dp audio condition
DP audio enablement code which is comparing intf_type, DRM_MODE_ENCODER_TMDS (= 2) with DRM_MODE_CONNECTOR_DisplayPort (= 10). Which would never succeed. Fix it to check for DRM_MODE_ENCODER_TMDS. Fixes: d13e36d7d222 ("drm/msm/dp: add audio support for Display Port on MSM") Reviewed-by: Abhinav Kumar Reviewed-by: Bjorn Andersson Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 +- 1 file changed, 1 insertion(+), 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 1e648db439f9..02d0fae1c6dc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1099,7 +1099,7 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc) } - if (dpu_enc->disp_info.intf_type == DRM_MODE_CONNECTOR_DisplayPort && + if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_TMDS && dpu_enc->cur_master->hw_mdptop && dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select) dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select( -- 2.34.1
[PATCH v2 7/7] drm/msm/dpu: pull connector from dpu_encoder_phys to dpu_encoder_virt
All physical encoders used by virtual encoder share the same connector, so pull the connector field from dpu_encoder_phys into dpu_encoder_virt structure. Otherwise code suggests that different phys_encs can have different connectors. Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 11 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 2 -- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index a8c9f5a4dd67..b23f12eb0e0e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -143,6 +143,7 @@ enum dpu_enc_rc_states { * link between encoder/crtc. However in this case we need * to track crtc in the disable() hook which is called * _after_ encoder_mask is cleared. + * @connector: If a mode is set, cached pointer to the active connector * @crtc_kickoff_cb: Callback into CRTC that will flush & start * all CTL paths * @crtc_kickoff_cb_data: Opaque user data given to crtc_kickoff_cb @@ -183,6 +184,7 @@ struct dpu_encoder_virt { bool intfs_swapped; struct drm_crtc *crtc; + struct drm_connector *connector; struct dentry *debugfs_root; struct mutex enc_lock; @@ -1010,6 +1012,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, cstate->num_mixers = num_lm; + dpu_enc->connector = conn_state->connector; + for (i = 0; i < dpu_enc->num_phys_encs; i++) { int num_blk; struct dpu_hw_blk *hw_blk[MAX_CHANNELS_PER_ENC]; @@ -1047,7 +1051,6 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, return; } - phys->connector = conn_state->connector; phys->cached_mode = crtc_state->adjusted_mode; if (phys->ops.atomic_mode_set) phys->ops.atomic_mode_set(phys, crtc_state, conn_state); @@ -1081,7 +1084,7 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc) if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI && !WARN_ON(dpu_enc->num_phys_encs == 0)) { - unsigned bpc = dpu_enc->phys_encs[0]->connector->display_info.bpc; + unsigned bpc = dpu_enc->connector->display_info.bpc; for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { if (!dpu_enc->hw_pp[i]) continue; @@ -1185,9 +1188,7 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) dpu_encoder_resource_control(drm_enc, DPU_ENC_RC_EVENT_STOP); - for (i = 0; i < dpu_enc->num_phys_encs; i++) { - dpu_enc->phys_encs[i]->connector = NULL; - } + dpu_enc->connector = NULL; DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n"); 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 6309c5e30d20..43ce56109c41 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -178,7 +178,6 @@ struct dpu_encoder_irq { * tied to a specific panel / sub-panel. Abstract type, sub-classed by * phys_vid or phys_cmd for video mode or command mode encs respectively. * @parent:Pointer to the containing virtual encoder - * @connector: If a mode is set, cached pointer to the active connector * @ops: Operations exposed to the virtual encoder * @parent_ops:Callbacks exposed by the parent to the phys_enc * @hw_mdptop: Hardware interface to the top registers @@ -207,7 +206,6 @@ struct dpu_encoder_irq { */ struct dpu_encoder_phys { struct drm_encoder *parent; - struct drm_connector *connector; struct dpu_encoder_phys_ops ops; const struct dpu_encoder_virt_ops *parent_ops; struct dpu_hw_mdp *hw_mdptop; -- 2.34.1
[PATCH v2 4/7] drm/msm/dpu: drop bus_scaling_client field
We do not use MSM bus client, so drop bus_scaling_client field from dpu_encoder_virt. Reviewed-by: Abhinav Kumar Reviewed-by: Bjorn Andersson Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 16ae0cccbbb1..f5bc15b2e56e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -127,7 +127,6 @@ enum dpu_enc_rc_states { * Virtual encoder registers itself with the DRM Framework as the encoder. * @base: drm_encoder base class for registration with DRM * @enc_spinlock: Virtual-Encoder-Wide Spin Lock for IRQ purposes - * @bus_scaling_client:Client handle to the bus scaling interface * @enabled: True if the encoder is active, protected by enc_lock * @num_phys_encs: Actual number of physical encoders contained. * @phys_encs: Container of physical encoders managed. @@ -172,7 +171,6 @@ enum dpu_enc_rc_states { struct dpu_encoder_virt { struct drm_encoder base; spinlock_t enc_spinlock; - uint32_t bus_scaling_client; bool enabled; -- 2.34.1
[PATCH v2 3/7] drm/msm/dpu: remove msm_dp cached in dpu_encoder_virt
Stop caching msm_dp instance in dpu_encoder_virt since it's not used now. Fixes: 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display enable and disable") Reviewed-by: Abhinav Kumar Reviewed-by: Bjorn Andersson Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 02d0fae1c6dc..16ae0cccbbb1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -168,7 +168,6 @@ 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; @@ -207,8 +206,6 @@ 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) @@ -2128,8 +2125,6 @@ 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[disp_info->h_tile_instance[0]]; INIT_DELAYED_WORK(_enc->delayed_off_work, dpu_encoder_off_work); -- 2.34.1
[PATCH v2 5/7] drm/msm/dpu: encoder: drop unused mode_fixup callback
Both cmd and vid backends provide useless mode_fixup() callback. Drop it. Reviewed-by: Bjorn Andersson Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c| 4 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 4 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 10 -- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 14 -- 4 files changed, 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 f5bc15b2e56e..5b2eeea37d54 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -602,10 +602,6 @@ static int dpu_encoder_virt_atomic_check( if (phys->ops.atomic_check) ret = phys->ops.atomic_check(phys, crtc_state, conn_state); - else if (phys->ops.mode_fixup) - if (!phys->ops.mode_fixup(phys, mode, adj_mode)) - ret = -EINVAL; - if (ret) { DPU_ERROR_ENC(dpu_enc, "mode unsupported, phys idx %d\n", i); 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 e7270eb6b84b..7b14948c4c87 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -84,7 +84,6 @@ struct dpu_encoder_virt_ops { * @is_master: Whether this phys_enc is the current master * encoder. Can be switched at enable time. Based * on split_role and current mode (CMD/VID). - * @mode_fixup:DRM Call. Fixup a DRM mode. * @mode_set: DRM Call. Set a DRM mode. * This likely caches the mode, for use at enable. * @enable:DRM Call. Enable a DRM mode. @@ -117,9 +116,6 @@ struct dpu_encoder_phys_ops { struct dentry *debugfs_root); void (*prepare_commit)(struct dpu_encoder_phys *encoder); bool (*is_master)(struct dpu_encoder_phys *encoder); - bool (*mode_fixup)(struct dpu_encoder_phys *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); void (*mode_set)(struct dpu_encoder_phys *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); 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 34a6940d12c5..45fe97fb612d 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 @@ -45,15 +45,6 @@ static bool dpu_encoder_phys_cmd_is_master(struct dpu_encoder_phys *phys_enc) return (phys_enc->split_role != ENC_ROLE_SLAVE); } -static bool dpu_encoder_phys_cmd_mode_fixup( - struct dpu_encoder_phys *phys_enc, - const struct drm_display_mode *mode, - struct drm_display_mode *adj_mode) -{ - DPU_DEBUG_CMDENC(to_dpu_encoder_phys_cmd(phys_enc), "\n"); - return true; -} - static void _dpu_encoder_phys_cmd_update_intf_cfg( struct dpu_encoder_phys *phys_enc) { @@ -732,7 +723,6 @@ static void dpu_encoder_phys_cmd_init_ops( ops->prepare_commit = dpu_encoder_phys_cmd_prepare_commit; ops->is_master = dpu_encoder_phys_cmd_is_master; ops->mode_set = dpu_encoder_phys_cmd_mode_set; - ops->mode_fixup = dpu_encoder_phys_cmd_mode_fixup; ops->enable = dpu_encoder_phys_cmd_enable; ops->disable = dpu_encoder_phys_cmd_disable; ops->destroy = dpu_encoder_phys_cmd_destroy; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index ddd9d89cd456..1831fe37c88c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -225,19 +225,6 @@ static void programmable_fetch_config(struct dpu_encoder_phys *phys_enc, spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); } -static bool dpu_encoder_phys_vid_mode_fixup( - struct dpu_encoder_phys *phys_enc, - const struct drm_display_mode *mode, - struct drm_display_mode *adj_mode) -{ - DPU_DEBUG_VIDENC(phys_enc, "\n"); - - /* -* Modifying mode has consequences when the mode comes back to us -*/ - return true; -} - static void dpu_encoder_phys_vid_setup_timing_engine( struct dpu_encoder_phys *phys_enc) { @@ -676,7 +663,6 @@ static void dpu_encoder_phys_vid_init_ops(struct
[PATCH v2 6/7] drm/msm/dpu: switch dpu_encoder to use atomic_mode_set
Make dpu_encoder use atomic_mode_set to receive connector and CRTC states as arguments rather than finding connector and CRTC by manually looping through the respective lists. Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 37 +-- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 8 ++-- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 18 ++--- .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 14 ++- 4 files changed, 21 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 5b2eeea37d54..a8c9f5a4dd67 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -947,16 +947,13 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, return 0; } -static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, - struct drm_display_mode *mode, - struct drm_display_mode *adj_mode) +static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, +struct drm_crtc_state *crtc_state, +struct drm_connector_state *conn_state) { struct dpu_encoder_virt *dpu_enc; struct msm_drm_private *priv; struct dpu_kms *dpu_kms; - struct list_head *connector_list; - struct drm_connector *conn = NULL, *conn_iter; - struct drm_crtc *drm_crtc; struct dpu_crtc_state *cstate; struct dpu_global_state *global_state; struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC]; @@ -976,7 +973,6 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, priv = drm_enc->dev->dev_private; dpu_kms = to_dpu_kms(priv->kms); - connector_list = _kms->dev->mode_config.connector_list; global_state = dpu_kms_get_existing_global_state(dpu_kms); if (IS_ERR_OR_NULL(global_state)) { @@ -986,22 +982,6 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, trace_dpu_enc_mode_set(DRMID(drm_enc)); - list_for_each_entry(conn_iter, connector_list, head) - if (conn_iter->encoder == drm_enc) - conn = conn_iter; - - if (!conn) { - DPU_ERROR_ENC(dpu_enc, "failed to find attached connector\n"); - return; - } else if (!conn->state) { - DPU_ERROR_ENC(dpu_enc, "invalid connector state\n"); - return; - } - - drm_for_each_crtc(drm_crtc, drm_enc->dev) - if (drm_crtc->state->encoder_mask & drm_encoder_mask(drm_enc)) - break; - /* Query resource that have been reserved in atomic check step. */ num_pp = dpu_rm_get_assigned_resources(_kms->rm, global_state, drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp, @@ -1018,7 +998,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i]) : NULL; - cstate = to_dpu_crtc_state(drm_crtc->state); + cstate = to_dpu_crtc_state(crtc_state); for (i = 0; i < num_lm; i++) { int ctl_idx = (i < num_ctl) ? i : (num_ctl-1); @@ -1067,9 +1047,10 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, return; } - phys->connector = conn->state->connector; - if (phys->ops.mode_set) - phys->ops.mode_set(phys, mode, adj_mode); + phys->connector = conn_state->connector; + phys->cached_mode = crtc_state->adjusted_mode; + if (phys->ops.atomic_mode_set) + phys->ops.atomic_mode_set(phys, crtc_state, conn_state); } } @@ -2084,7 +2065,7 @@ 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, + .atomic_mode_set = dpu_encoder_virt_atomic_mode_set, .disable = dpu_encoder_virt_disable, .enable = dpu_encoder_virt_enable, .atomic_check = dpu_encoder_virt_atomic_check, 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 7b14948c4c87..6309c5e30d20 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -84,7 +84,7 @@ struct dpu_encoder_virt_ops { * @is_master: Whether this phys_enc is the current master * encoder. Can be switched at enable time. Based * on split_role and current
[PATCH v2 2/7] drm/msm: move struct msm_display_info to dpu driver
The msm_display_info structure is not used by the rest of msm driver, so move it into the dpu1 (dpu_encoder.h to be precise). Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 18 ++ drivers/gpu/drm/msm/msm_drv.h | 18 -- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index e241914a9677..ebe3944355bb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -34,6 +34,24 @@ struct dpu_encoder_hw_resources { void dpu_encoder_get_hw_resources(struct drm_encoder *encoder, struct dpu_encoder_hw_resources *hw_res); +/** + * struct msm_display_info - defines display properties + * @intf_type: DRM_MODE_ENCODER_ type + * @capabilities: Bitmask of display flags + * @num_of_h_tiles: Number of horizontal tiles in case of split interface + * @h_tile_instance:Controller instance used per tile. Number of elements is + * based on num_of_h_tiles + * @is_te_using_watchdog_timer: Boolean to indicate watchdog TE is + * used instead of panel TE in cmd mode panels + */ +struct msm_display_info { + int intf_type; + uint32_t capabilities; + uint32_t num_of_h_tiles; + uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY]; + bool is_te_using_watchdog_timer; +}; + /** * dpu_encoder_assign_crtc - Link the encoder to the crtc it's assigned to * @encoder: encoder pointer diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index d7574e6bd4e4..16f9e25ee19e 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -109,24 +109,6 @@ struct msm_display_topology { u32 num_dspp; }; -/** - * struct msm_display_info - defines display properties - * @intf_type: DRM_MODE_ENCODER_ type - * @capabilities: Bitmask of display flags - * @num_of_h_tiles: Number of horizontal tiles in case of split interface - * @h_tile_instance:Controller instance used per tile. Number of elements is - * based on num_of_h_tiles - * @is_te_using_watchdog_timer: Boolean to indicate watchdog TE is - * used instead of panel TE in cmd mode panels - */ -struct msm_display_info { - int intf_type; - uint32_t capabilities; - uint32_t num_of_h_tiles; - uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY]; - bool is_te_using_watchdog_timer; -}; - /* Commit/Event thread specific structure */ struct msm_drm_thread { struct drm_device *dev; -- 2.34.1
[PATCH v2 0/7] drm/msm/dpu: cleanup dpu encoder code
This patchset targets DPU encoder code, removing unused artifacts (empty callbacks, MSM bus client id, etc). Changes since v2: - Expand commit message of 7th patch (pull connector from dpu_encoder_phys to dpu_encoder_virt) - Drop intf_type patch for now, as it causes controversy Changes since v1: - Split dp audio fixup from the intf_type patch - Remove atomic_check() removal, used by the posted WB support Dmitry Baryshkov (7): drm/msm/dpu: fix dp audio condition drm/msm: move struct msm_display_info to dpu driver drm/msm/dpu: remove msm_dp cached in dpu_encoder_virt drm/msm/dpu: drop bus_scaling_client field drm/msm/dpu: encoder: drop unused mode_fixup callback drm/msm/dpu: switch dpu_encoder to use atomic_mode_set drm/msm/dpu: pull connector from dpu_encoder_phys to dpu_encoder_virt drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 59 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 18 ++ .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 14 ++--- .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 28 ++--- .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 28 ++--- drivers/gpu/drm/msm/msm_drv.h | 18 -- 6 files changed, 45 insertions(+), 120 deletions(-) -- 2.34.1
[pull] radeon, amdgpu drm-fixes-5.17
Hi Dave, Daniel, Fixes for 5.17. The following changes since commit 754e0b0e35608ed5206d6a67a791563c631cec07: Linux 5.17-rc4 (2022-02-13 12:13:30 -0800) are available in the Git repository at: https://gitlab.freedesktop.org/agd5f/linux.git tags/amd-drm-fixes-5.17-2022-02-16 for you to fetch changes up to 364438fd629f7611a84c8e6d7de91659300f1502: drm/radeon: Fix backlight control on iMac 12,1 (2022-02-14 15:01:46 -0500) amd-drm-fixes-5.17-2022-02-16: amdgpu: - Stable pstate clock fixes for Dimgrey Cavefish and Beige Goby - S0ix SDMA fix - Yellow Carp GPU reset fix radeon: - Backlight fix for iMac 12,1 Evan Quan (1): drm/amd/pm: correct UMD pstate clocks for Dimgrey Cavefish and Beige Goby Nicholas Bishop (1): drm/radeon: Fix backlight control on iMac 12,1 Rajib Mahapatra (1): drm/amdgpu: skipping SDMA hw_init and hw_fini for S0ix. Yifan Zhang (1): drm/amd/pm: correct the sequence of sending gpu reset msg drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 8 +++ .../drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c| 26 +- .../drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h| 8 +++ .../gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 9 ++-- drivers/gpu/drm/radeon/atombios_encoders.c | 3 ++- 5 files changed, 41 insertions(+), 13 deletions(-)
[PATCH 13/13] drm_print: use DEFINE_DYNAMIC_DEBUG_CLASSBITS for drm.debug
if CONFIG_DRM_USE_DYNAMIC_DEBUG=y, use new macro to create the sysfs bitmap to control drm.debug callsites. DEFINE_DYNAMIC_DEBUG_CLASSBITS( debug, __drm_debug, "p", "drm.debug - control summary", /* inline vector of _ddebug.class_id's to be controlled, max 14 vals */ DRM_UT_CORE, DRM_UT_DRIVER, DRM_UT_KMS, DRM_UT_PRIME, DRM_UT_ATOMIC, DRM_UT_VBL, DRM_UT_STATE, DRM_UT_LEASE, DRM_UT_DP, DRM_UT_DRMRES ); NOTES: The @_flgs used here is "p", so this bitmap enables input to syslog only, matching legacy behavior. Also, no "fmlt" decorator flags are used here; that is discouraged, as it then toggles those flags along with the "p". This would undo any customizations a user added once the sysfs-knob is used. Still, there may be cases/reasons. _ddebug.class_id is uint:4, values 0-14 are valid. 15 is reserved for non-classified callsites (regular pr_debugs). Using it terminates the scan, don't use it halfway through your list. Signed-off-by: Jim Cromie --- drivers/gpu/drm/drm_print.c | 20 ++-- include/drm/drm_print.h | 4 ++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c index c9b2a2ab0d3d..d916daa384e5 100644 --- a/drivers/gpu/drm/drm_print.c +++ b/drivers/gpu/drm/drm_print.c @@ -38,7 +38,7 @@ * __drm_debug: Enable debug output. * Bitmask of DRM_UT_x. See include/drm/drm_print.h for details. */ -unsigned int __drm_debug; +unsigned long __drm_debug; EXPORT_SYMBOL(__drm_debug); MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug category.\n" @@ -50,7 +50,23 @@ 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); + +#if !defined(CONFIG_DRM_USE_DYNAMIC_DEBUG) +module_param_named(debug, __drm_debug, ulong, 0600); +#else +DEFINE_DYNAMIC_DEBUG_CLASSBITS(debug, __drm_debug, "p", + "enable drm.debug categories - 1 bit per category", + DRM_UT_CORE, + DRM_UT_DRIVER, + DRM_UT_KMS, + DRM_UT_PRIME, + DRM_UT_ATOMIC, + DRM_UT_VBL, + DRM_UT_STATE, + DRM_UT_LEASE, + DRM_UT_DP, + DRM_UT_DRMRES); +#endif void __drm_puts_coredump(struct drm_printer *p, const char *str) { diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h index 13d52b60f388..419140bf992d 100644 --- a/include/drm/drm_print.h +++ b/include/drm/drm_print.h @@ -36,7 +36,7 @@ #include /* Do *not* use outside of drm_print.[ch]! */ -extern unsigned int __drm_debug; +extern unsigned long __drm_debug; /** * DOC: print @@ -527,7 +527,7 @@ __printf(1, 2) void __drm_err(const char *format, ...); #if !defined(CONFIG_DRM_USE_DYNAMIC_DEBUG) -#define __drm_dbg(fmt, ...)___drm_dbg(NULL, fmt, ##__VA_ARGS__) +#define __drm_dbg(cat, fmt, ...) ___drm_dbg(NULL, cat, fmt, ##__VA_ARGS__) #else #define __drm_dbg(cat, fmt, ...) \ _dynamic_func_call_cls(cat, fmt, ___drm_dbg,\ -- 2.35.1
[PATCH 12/13] drm_print: add _ddebug desc to drm_*dbg prototypes
Add a struct _ddebug ptr to drm_dbg() and drm_dev_dbg() protos. And upgrade the current use of _dynamic_func_call_no_desc(); ie drop the '_no_desc', since the factory macro's callees (these 2 functions) are now expecting the arg. This lets those functions act more like pr_debug(). It also means that these functions don't just get the decorations from an underlying implementation. DRM already has standards for logging/messaging; tossing optional decorations on top may not help. use that info provide it to dyndbg [1], which can then control debug enablement and decoration for all those drm.debug callsites. For CONFIG_DRM_USE_DYNAMIC_DEBUG=N, just pass null. NB: desc->class_id is redundant with category, but !!desc dependent. Signed-off-by: Jim Cromie --- drivers/gpu/drm/drm_print.c | 23 +-- include/drm/drm_print.h | 23 --- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c index 24c57b92dc69..c9b2a2ab0d3d 100644 --- a/drivers/gpu/drm/drm_print.c +++ b/drivers/gpu/drm/drm_print.c @@ -255,8 +255,8 @@ void drm_dev_printk(const struct device *dev, const char *level, } EXPORT_SYMBOL(drm_dev_printk); -void __drm_dev_dbg(const struct device *dev, enum drm_debug_category category, - const char *format, ...) +void __drm_dev_dbg(struct _ddebug *desc, const struct device *dev, + enum drm_debug_category category, const char *format, ...) { struct va_format vaf; va_list args; @@ -264,22 +264,25 @@ void __drm_dev_dbg(const struct device *dev, enum drm_debug_category category, if (!__drm_debug_enabled(category)) return; + /* we know we are printing for either syslog, tracefs, or both */ va_start(args, format); vaf.fmt = format; vaf.va = - if (dev) - dev_printk(KERN_DEBUG, dev, "[" DRM_NAME ":%ps] %pV", - __builtin_return_address(0), ); - else - printk(KERN_DEBUG "[" DRM_NAME ":%ps] %pV", - __builtin_return_address(0), ); - + if (dev) { + if (dyndbg_site_is_printing(desc)) + dev_printk(KERN_DEBUG, dev, "[" DRM_NAME ":%ps] %pV", + __builtin_return_address(0), ); + } else { + if (dyndbg_site_is_printing(desc)) + printk(KERN_DEBUG "[" DRM_NAME ":%ps] %pV", + __builtin_return_address(0), ); + } va_end(args); } EXPORT_SYMBOL(__drm_dev_dbg); -void ___drm_dbg(enum drm_debug_category category, const char *format, ...) +void ___drm_dbg(struct _ddebug *desc, enum drm_debug_category category, const char *format, ...) { struct va_format vaf; va_list args; diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h index 38ef044d786e..13d52b60f388 100644 --- a/include/drm/drm_print.h +++ b/include/drm/drm_print.h @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -361,9 +362,9 @@ static inline bool drm_debug_enabled(enum drm_debug_category category) __printf(3, 4) void drm_dev_printk(const struct device *dev, const char *level, const char *format, ...); -__printf(3, 4) -void __drm_dev_dbg(const struct device *dev, enum drm_debug_category category, -const char *format, ...); +__printf(4, 5) +void __drm_dev_dbg(struct _ddebug *desc, const struct device *dev, + enum drm_debug_category category, const char *format, ...); /** * DRM_DEV_ERROR() - Error output. @@ -413,11 +414,11 @@ void __drm_dev_dbg(const struct device *dev, enum drm_debug_category category, #if !defined(CONFIG_DRM_USE_DYNAMIC_DEBUG) #define drm_dev_dbg(dev, cat, fmt, ...)\ - __drm_dev_dbg(dev, cat, fmt, ##__VA_ARGS__) + __drm_dev_dbg(NULL, dev, cat, fmt, ##__VA_ARGS__) #else #define drm_dev_dbg(dev, cat, fmt, ...)\ - _dynamic_func_call_no_desc(fmt, __drm_dev_dbg, \ - dev, cat, fmt, ##__VA_ARGS__) + _dynamic_func_call_cls(cat, fmt, __drm_dev_dbg, \ + dev, cat, fmt, ##__VA_ARGS__) #endif /** @@ -520,17 +521,17 @@ void __drm_dev_dbg(const struct device *dev, enum drm_debug_category category, * Prefer drm_device based logging over device or prink based logging. */ -__printf(2, 3) -void ___drm_dbg(enum drm_debug_category category, const char *format, ...); +__printf(3, 4) +void ___drm_dbg(struct _ddebug *desc, enum drm_debug_category category, const char *format, ...); __printf(1, 2) void __drm_err(const char *format, ...); #if !defined(CONFIG_DRM_USE_DYNAMIC_DEBUG) -#define __drm_dbg(fmt, ...)___drm_dbg(fmt, ##__VA_ARGS__) +#define __drm_dbg(fmt, ...)
[PATCH 11/13] drm_print: prefer bare printk KERN_DEBUG on generic fn
drm_print.c calls pr_debug() just once, from __drm_printfn_debug(), which is a generic/service fn. The callsite is compile-time enabled by DEBUG in both DYNAMIC_DEBUG=y/n builds. For dyndbg builds, reverting this callsite back to bare printk is correcting a few anti-features: 1- callsite is generic, serves multiple drm users. its hardwired on currently could accidentally: #> echo -p > /proc/dynamic_debug/control 2- optional "decorations" by dyndbg are unhelpful/misleading they describe only the generic site, not end users IOW, 1,2 are unhelpful at best, and possibly confusing. reverting yields a nominal data and text shrink: textdata bss dec hex filename 462583 36604 54592 553779 87333 /lib/modules/5.16.0-rc4-lm1-8-ged3eac8ceeea/kernel/drivers/gpu/drm/drm.ko 462515 36532 54592 553639 872a7 /lib/modules/5.16.0-rc4-lm1-9-g6ce0b88d2539-dirty/kernel/drivers/gpu/drm/drm.ko NB: this was noticed using _drm_debug_enabled(), added earlier. Signed-off-by: Jim Cromie --- drivers/gpu/drm/drm_print.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c index 92e6e18026da..24c57b92dc69 100644 --- a/drivers/gpu/drm/drm_print.c +++ b/drivers/gpu/drm/drm_print.c @@ -23,8 +23,6 @@ * Rob Clark */ -#define DEBUG /* for pr_debug() */ - #include #include @@ -162,7 +160,8 @@ EXPORT_SYMBOL(__drm_printfn_info); void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf) { - pr_debug("%s %pV", p->prefix, vaf); + /* pr_debug callsite decorations are unhelpful here */ + printk(KERN_DEBUG "%s %pV", p->prefix, vaf); } EXPORT_SYMBOL(__drm_printfn_debug); -- 2.35.1
[PATCH 09/13] drm_print: wrap drm_*_dbg in dyndbg jumplabel
For CONFIG_DRM_USE_DYNAMIC_DEBUG=y, wrap drm_dbg() & drm_dev_dbg() in one of dyndbg's Factory macros: _dynamic_func_call_no_desc(). This makes the (~4000) callsites controllable, typically by class: # 0 is DRM_UT_CORE #> echo module drm class 0 +p > /proc/dynamic_debug/control =N: keeps direct forwarding: drm_*_dbg -> __drm_*_dbg() I added the CONFIG_DRM_USE_DYNAMIC_DEBUG item because of the .data footprint cost of per-callsite control; 56 bytes/site * ~2k,4k callsites (for i915, amdgpu), which is significant enough that a user might not want it. Using CONFIG_DYNAMIC_DEBUG_CORE only eliminates the builtin portion, leaving only drm modules, but still 200k of module data is a lot. Signed-off-by: Jim Cromie --- drivers/gpu/drm/Kconfig | 12 drivers/gpu/drm/Makefile | 2 ++ include/drm/drm_print.h | 12 3 files changed, 26 insertions(+) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index b1f22e457fd0..ec14a1cd4449 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -63,6 +63,18 @@ config DRM_DEBUG_MM If in doubt, say "N". +config DRM_USE_DYNAMIC_DEBUG + bool "use dynamic debug to implement drm.debug" + default y + depends on DRM + depends on DYNAMIC_DEBUG || DYNAMIC_DEBUG_CORE + depends on JUMP_LABEL + help + Use dynamic-debug to avoid drm_debug_enabled() runtime overheads. + Due to callsite counts in DRM drivers (~4k in amdgpu) and 56 + bytes per callsite, the .data costs can be substantial, and + are therefore configurable. + config DRM_DEBUG_SELFTEST tristate "kselftests for DRM" depends on DRM diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 301a44dc18e3..24e6410d6c0e 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -3,6 +3,8 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. +CFLAGS-$(CONFIG_DRM_USE_DYNAMIC_DEBUG) += -DDYNAMIC_DEBUG_MODULE + drm-y := drm_aperture.o drm_auth.o drm_cache.o \ drm_file.o drm_gem.o drm_ioctl.o \ drm_drv.o \ diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h index 4bed99326631..06f0ee06be1f 100644 --- a/include/drm/drm_print.h +++ b/include/drm/drm_print.h @@ -383,8 +383,14 @@ void __drm_dev_dbg(const struct device *dev, enum drm_debug_category category, } \ }) +#if !defined(CONFIG_DRM_USE_DYNAMIC_DEBUG) #define drm_dev_dbg(dev, cat, fmt, ...)\ __drm_dev_dbg(dev, cat, fmt, ##__VA_ARGS__) +#else +#define drm_dev_dbg(dev, cat, fmt, ...)\ + _dynamic_func_call_no_desc(fmt, __drm_dev_dbg, \ + dev, cat, fmt, ##__VA_ARGS__) +#endif /** * DRM_DEV_DEBUG() - Debug output for generic drm code @@ -491,7 +497,13 @@ void ___drm_dbg(enum drm_debug_category category, const char *format, ...); __printf(1, 2) void __drm_err(const char *format, ...); +#if !defined(CONFIG_DRM_USE_DYNAMIC_DEBUG) #define __drm_dbg(fmt, ...)___drm_dbg(fmt, ##__VA_ARGS__) +#else +#define __drm_dbg(cat, fmt, ...) \ + _dynamic_func_call_no_desc(fmt, ___drm_dbg, \ + cat, fmt, ##__VA_ARGS__) +#endif /* Macros to make printk easier */ -- 2.35.1
[PATCH 10/13] drm_print: refine drm_debug_enabled for dyndbg+jump-label
In order to use dynamic-debug's jump-label optimization in drm-debug, its clarifying to refine drm_debug_enabled into 3 uses: 1. drm_debug_enabled - legacy, public 2. __drm_debug_enabled - optimized for dyndbg jump-label enablement. 3. _drm_debug_enabled - pr_debug instrumented, observable 1. The legacy version always checks the bits. 2. is privileged, for use by __drm_dbg(), __drm_dev_dbg(), which do an early return unless the category is enabled (free of call/NOOP side effects). For dyndbg builds, debug callsites are selectively "pre-enabled", so __drm_debug_enabled() short-circuits to true there. Remaining callers of 1 may be able to use 2, case by case. 3. is 1st wrapped in a macro, with a pr_debug, which reports each usage in /proc/dynamic_debug/control, making it observable in the logs. The macro lets the pr_debug see the real caller, not an inline function. When plugged into 1, it identified ~10 remaining callers of the function, leading to the follow-on cleanup patch, and would allow activating the pr_debugs, estimating the callrate, and the potential savings by using the wrapper macro. It is unused ATM, but it fills out the picture. Signed-off-by: Jim Cromie --- drivers/gpu/drm/drm_print.c | 4 ++-- include/drm/drm_print.h | 28 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c index e45ba224e57c..92e6e18026da 100644 --- a/drivers/gpu/drm/drm_print.c +++ b/drivers/gpu/drm/drm_print.c @@ -262,7 +262,7 @@ void __drm_dev_dbg(const struct device *dev, enum drm_debug_category category, struct va_format vaf; va_list args; - if (!drm_debug_enabled(category)) + if (!__drm_debug_enabled(category)) return; va_start(args, format); @@ -285,7 +285,7 @@ void ___drm_dbg(enum drm_debug_category category, const char *format, ...) struct va_format vaf; va_list args; - if (!drm_debug_enabled(category)) + if (!__drm_debug_enabled(category)) return; va_start(args, format); diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h index 06f0ee06be1f..38ef044d786e 100644 --- a/include/drm/drm_print.h +++ b/include/drm/drm_print.h @@ -319,11 +319,39 @@ enum drm_debug_category { DRM_UT_DRMRES }; +/* + * 3 name flavors of drm_debug_enabled: + * drm_debug_enabled - public/legacy, always checks bits + * _drm_debug_enabled - instrumented to observe call-rates, est overheads. + * __drm_debug_enabled - privileged - knows jump-label state, can short-circuit + */ static inline bool drm_debug_enabled(enum drm_debug_category category) { return unlikely(__drm_debug & BIT(category)); } +/* + * Wrap fn in macro, so that the pr_debug sees the actual caller, not + * the inline fn. Using this name creates a callsite entry / control + * point in /proc/dynamic_debug/control. + */ +#define _drm_debug_enabled(category) \ + ({ \ + pr_debug("todo: maybe avoid via dyndbg\n"); \ + drm_debug_enabled(category);\ + }) + +#if defined(CONFIG_DRM_USE_DYNAMIC_DEBUG) +/* + * dyndbg is wrapping the drm.debug API, so as to avoid the runtime + * bit-test overheads of drm_debug_enabled() in those api calls. + * In this case, executed callsites are known enabled, so true. + */ +#define __drm_debug_enabled(category) true +#else +#define __drm_debug_enabled(category) drm_debug_enabled(category) +#endif + /* * struct device based logging * -- 2.35.1
[PATCH 07/13] drm_print: condense enum drm_debug_category
enum drm_debug_category has 10 "classes", explicitly initialized with 0x-bitmasks which could be simplified as BIT(X)s. But lets go further: use natural enumeration (int, starting at 0), and do the BIT(cat) in drm_debug_enabled(cat) at runtime. While this slightly pessimizes the bit-test, the category now fits in 4 bits, allowing it in struct _ddebug.class_id:4. This sets us up to adapt drm to use dyndbg with JUMP_LABEL, thus avoiding all those bit-tests anyway. Signed-off-by: Jim Cromie --- include/drm/drm_print.h | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h index 22fabdeed297..b3b470440e46 100644 --- a/include/drm/drm_print.h +++ b/include/drm/drm_print.h @@ -279,49 +279,49 @@ enum drm_debug_category { * @DRM_UT_CORE: Used in the generic drm code: drm_ioctl.c, drm_mm.c, * drm_memory.c, ... */ - DRM_UT_CORE = 0x01, + DRM_UT_CORE, /** * @DRM_UT_DRIVER: Used in the vendor specific part of the driver: i915, * radeon, ... macro. */ - DRM_UT_DRIVER = 0x02, + DRM_UT_DRIVER, /** * @DRM_UT_KMS: Used in the modesetting code. */ - DRM_UT_KMS = 0x04, + DRM_UT_KMS, /** * @DRM_UT_PRIME: Used in the prime code. */ - DRM_UT_PRIME= 0x08, + DRM_UT_PRIME, /** * @DRM_UT_ATOMIC: Used in the atomic code. */ - DRM_UT_ATOMIC = 0x10, + DRM_UT_ATOMIC, /** * @DRM_UT_VBL: Used for verbose debug message in the vblank code. */ - DRM_UT_VBL = 0x20, + DRM_UT_VBL, /** * @DRM_UT_STATE: Used for verbose atomic state debugging. */ - DRM_UT_STATE= 0x40, + DRM_UT_STATE, /** * @DRM_UT_LEASE: Used in the lease code. */ - DRM_UT_LEASE= 0x80, + DRM_UT_LEASE, /** * @DRM_UT_DP: Used in the DP code. */ - DRM_UT_DP = 0x100, + DRM_UT_DP, /** * @DRM_UT_DRMRES: Used in the drm managed resources code. */ - DRM_UT_DRMRES = 0x200, + DRM_UT_DRMRES }; static inline bool drm_debug_enabled(enum drm_debug_category category) { - return unlikely(__drm_debug & category); + return unlikely(__drm_debug & BIT(category)); } /* -- 2.35.1
[PATCH 08/13] drm_print: interpose drm_*dbg with forwarding macros
drm_dev_dbg() & drm_dbg() sit below the categorized layer of the DRM debug API, and implement most of it. These are good places to insert dynamic-debug jump-label mechanics, allowing DRM to avoid the runtime cost of drm_debug_enabled(). Set up for this by changing the func names by adding '__' prefixes, and define forwarding macros to the new names. no functional changes. memory cost baseline: (unchanged) bash-5.1# drms_load [9.220389] dyndbg: 1 debug prints in module drm [9.224426] ACPI: bus type drm_connector registered [9.302192] dyndbg: 2 debug prints in module ttm [9.305033] dyndbg: 8 debug prints in module video [9.627563] dyndbg: 127 debug prints in module i915 [9.721505] AMD-Vi: AMD IOMMUv2 functionality not available on this system - This is not a bug. [ 10.091345] dyndbg: 2196 debug prints in module amdgpu [ 10.106589] [drm] amdgpu kernel modesetting enabled. [ 10.107270] amdgpu: CRAT table not found [ 10.107926] amdgpu: Virtual CRAT table created for CPU [ 10.108398] amdgpu: Topology: Add CPU node [ 10.168507] dyndbg: 3 debug prints in module wmi [ 10.329587] dyndbg: 3 debug prints in module nouveau Signed-off-by: Jim Cromie --- drivers/gpu/drm/drm_print.c | 10 +- include/drm/drm_print.h | 9 +++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c index f783d4963d4b..e45ba224e57c 100644 --- a/drivers/gpu/drm/drm_print.c +++ b/drivers/gpu/drm/drm_print.c @@ -256,8 +256,8 @@ void drm_dev_printk(const struct device *dev, const char *level, } EXPORT_SYMBOL(drm_dev_printk); -void drm_dev_dbg(const struct device *dev, enum drm_debug_category category, -const char *format, ...) +void __drm_dev_dbg(const struct device *dev, enum drm_debug_category category, + const char *format, ...) { struct va_format vaf; va_list args; @@ -278,9 +278,9 @@ void drm_dev_dbg(const struct device *dev, enum drm_debug_category category, va_end(args); } -EXPORT_SYMBOL(drm_dev_dbg); +EXPORT_SYMBOL(__drm_dev_dbg); -void __drm_dbg(enum drm_debug_category category, const char *format, ...) +void ___drm_dbg(enum drm_debug_category category, const char *format, ...) { struct va_format vaf; va_list args; @@ -297,7 +297,7 @@ void __drm_dbg(enum drm_debug_category category, const char *format, ...) va_end(args); } -EXPORT_SYMBOL(__drm_dbg); +EXPORT_SYMBOL(___drm_dbg); void __drm_err(const char *format, ...) { diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h index b3b470440e46..4bed99326631 100644 --- a/include/drm/drm_print.h +++ b/include/drm/drm_print.h @@ -334,7 +334,7 @@ __printf(3, 4) void drm_dev_printk(const struct device *dev, const char *level, const char *format, ...); __printf(3, 4) -void drm_dev_dbg(const struct device *dev, enum drm_debug_category category, +void __drm_dev_dbg(const struct device *dev, enum drm_debug_category category, const char *format, ...); /** @@ -383,6 +383,9 @@ void drm_dev_dbg(const struct device *dev, enum drm_debug_category category, } \ }) +#define drm_dev_dbg(dev, cat, fmt, ...)\ + __drm_dev_dbg(dev, cat, fmt, ##__VA_ARGS__) + /** * DRM_DEV_DEBUG() - Debug output for generic drm code * @@ -484,10 +487,12 @@ void drm_dev_dbg(const struct device *dev, enum drm_debug_category category, */ __printf(2, 3) -void __drm_dbg(enum drm_debug_category category, const char *format, ...); +void ___drm_dbg(enum drm_debug_category category, const char *format, ...); __printf(1, 2) void __drm_err(const char *format, ...); +#define __drm_dbg(fmt, ...)___drm_dbg(fmt, ##__VA_ARGS__) + /* Macros to make printk easier */ #define _DRM_PRINTK(once, level, fmt, ...) \ -- 2.35.1
[PATCH 06/13] dyndbg: abstract dyndbg_site_is_printing
Hide flags test in a macro. no functional changes. Signed-off-by: Jim Cromie --- include/linux/dynamic_debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index 664bb83778d2..106065244f73 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -56,7 +56,7 @@ struct _ddebug { #endif } __attribute__((aligned(8))); - +#define dyndbg_site_is_printing(desc) (desc->flags & _DPRINTK_FLAGS_PRINT) #if defined(CONFIG_DYNAMIC_DEBUG_CORE) -- 2.35.1
[PATCH 05/13] dyndbg: improve change-info to have old and new
move site.flag update after the v4pr_info("change") message, and improve the message to print both old and new flag values. Heres new form: dyndbg: changed net/ipv4/tcp.c:2424 [tcp]tcp_recvmsg_locked pT -> _ Signed-off-by: Jim Cromie --- lib/dynamic_debug.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index b72632212a65..77db640396a8 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -158,7 +158,7 @@ static int ddebug_change(const struct ddebug_query *query, struct ddebug_table *dt; unsigned int newflags; unsigned int nfound = 0; - struct flagsbuf fbuf; + struct flagsbuf fbuf, nbuf; /* search for matching ddebugs */ mutex_lock(_lock); @@ -223,11 +223,12 @@ static int ddebug_change(const struct ddebug_query *query, static_branch_enable(>key.dd_key_true); } #endif + v4pr_info("changed %s:%d [%s]%s %s -> %s\n", + trim_prefix(dp->filename), dp->lineno, + dt->mod_name, dp->function, + ddebug_describe_flags(dp->flags, ), + ddebug_describe_flags(newflags, )); dp->flags = newflags; - v4pr_info("changed %s:%d [%s]%s =%s\n", -trim_prefix(dp->filename), dp->lineno, -dt->mod_name, dp->function, -ddebug_describe_flags(dp->flags, )); } } mutex_unlock(_lock); -- 2.35.1
[PATCH 04/13] dyndbg: drop EXPORTed dynamic_debug_exec_queries
This exported fn is effectively obsoleted by Commit:HEAD~2, so remove it. The export was added here: commit a2d375eda771 ("dyndbg: refine export, rename to dynamic_debug_exec_queries()") commit 4c0d77828d4f ("dyndbg: export ddebug_exec_queries") Its intent was to allow drm.debug to use the exported function to implement its drm.debug bitmap api using dynamic_debug. Instead, HEAD~2 implements the bitmap inside dyndbg, and exposes it in a macro declarator, and HEAD~1 uses the macro to connect __drm_debug to the supporting callbacks. Since there are no other expected users, and any prospects would likely reuse the bitmap or a straightforward extension of it, we can drop this function until its really needed. This also drops the CONFIG_DYNAMIC_DEBUG=N stub-func, and its pr_warn(), which I avoided in 2012, then added in 2020 :-/ Signed-off-by: Jim Cromie --- include/linux/dynamic_debug.h | 9 - lib/dynamic_debug.c | 29 - 2 files changed, 38 deletions(-) diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index e83c4e36ad29..664bb83778d2 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -60,9 +60,6 @@ struct _ddebug { #if defined(CONFIG_DYNAMIC_DEBUG_CORE) -/* exported for module authors to exercise >control */ -int dynamic_debug_exec_queries(const char *query, const char *modname); - int ddebug_add_module(struct _ddebug *tab, unsigned int n, const char *modname); extern int ddebug_remove_module(const char *mod_name); @@ -253,12 +250,6 @@ static inline int ddebug_dyndbg_module_param_cb(char *param, char *val, rowsize, groupsize, buf, len, ascii); \ } while (0) -static inline int dynamic_debug_exec_queries(const char *query, const char *modname) -{ - pr_warn("kernel not built with CONFIG_DYNAMIC_DEBUG_CORE\n"); - return 0; -} - struct kernel_param; static inline int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp) { return 0; } diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 262178167358..b72632212a65 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -582,35 +582,6 @@ static int ddebug_exec_queries(char *query, const char *modname) return nfound; } -/** - * dynamic_debug_exec_queries - select and change dynamic-debug prints - * @query: query-string described in admin-guide/dynamic-debug-howto - * @modname: string containing module name, usually _name - * - * This uses the >/proc/dynamic_debug/control reader, allowing module - * authors to modify their dynamic-debug callsites. The modname is - * canonically struct module.mod_name, but can also be null or a - * module-wildcard, for example: "drm*". - */ -int dynamic_debug_exec_queries(const char *query, const char *modname) -{ - int rc; - char *qry; /* writable copy of query */ - - if (!query) { - pr_err("non-null query/command string expected\n"); - return -EINVAL; - } - qry = kstrndup(query, PAGE_SIZE, GFP_KERNEL); - if (!qry) - return -ENOMEM; - - rc = ddebug_exec_queries(qry, modname); - kfree(qry); - return rc; -} -EXPORT_SYMBOL_GPL(dynamic_debug_exec_queries); - #ifdef CONFIG_MODULES #define KP_MOD_NAME kp->mod->name #else -- 2.35.1
[PATCH 03/13] dyndbg: add DEFINE_DYNAMIC_DEBUG_CLASSBITS macro and callbacks
DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, var, bitmap_desc, classes..) allows users to create a drm.debug style (bitmap) sysfs interface, to control sets of pr_debug's according to their .class_id's This wraps existing "class" keyword and behavior: echo "module drm -p ; module drm class 0 +p ; module drm class 2 +p" >control With the macro in use, this is equivalent: echo 0x05 > /sys/module/drm/parameters/debug To use: DEFINE_DYNAMIC_DEBUG_CLASSBITS(debug, __drm_debug, "pmfl", "drm.debug - bits => categories:", /* vector of uint:4 symbols, ala enum drm_debug_category, 15 is EOL */ DRM_UT_CORE, DRM_UT_DRIVER, DRM_UT_KMS ... ); The 3rd arg is a string with any of the dyndbg.flags [pmflt_]+ Full exposure of the flags here lets the module author: - fully customize/take-over the decorations of enabled sites. generally leaving decorations to user is preferred. - aim the debug-stream: now printk, later tracefs. generally toggling both together is silly iface doesnt care about new flags added later - declare 2 separate sysfs-knobs, one each for p, T, if desired. - decorations are per callsite, shared across sysfs-knobs for any controlled classes To support the macro, the patch adds: - int param_set_dyndbg_classbits() - int param_get_dyndbg_classbits() - struct kernel_param_ops param_ops_dyndbg_classbits Following the model of kernel/params.c STANDARD_PARAM_DEFS, these are non-static and exported. get/set use an augmented kernel_param; the arg refs a new struct dyndbg_bitmap_param containing: A- the vector of classes (drm.debug "categories") being controlled This in-line vector of constants (uint [0-14]) specifies a sequence of controlling bits (by position, starting at 0) with the values naming the class_id's mapped to that bit. A value of _DPRINTK_SITE_UNCLASSED terminates the vector processing by param_set_dyndbg_classbits(), and is appended by the macro to insure a defined termination after max 15 classes are applied. Technically, the vector is a flex-array, but its size is practically limited to max 15 in length (repeats are pointless). B- a pointer to the user module's ulong holding the bits/state. By accessing client's bit-state, we coordinate with existing code that still uses drm_debug_enabled(), so they work unchanged. The change to ulong allows use of BIT() etc. NOTES: _DPRINTK_SITE_UNCLASSED = 15, ie 2**CLS_BITS-1, deserves special mention; it already marks all existing pr-debug callsites, only the new drm.debug callsites are initialized to other (DRM_UT_*) values. _DPRINTK_SITE_UNCLASSED is used in param_set_dyndbg_classbits() to limit the range of bits that are processed to what fits in uint:4. It also terminates the class-id list passed into the macro, so dont use it halfway through your list of classes-to-control. param_set_dyndbg_classbits() compares new vs old bits, and only updates each class on changes. This maximally preserves the underlying state, which may have been customized at some point via `echo $cmd >control`. So if users really want to know that all prdbgs are set precisely, they must pre-clear then set. Identity mapping in (A) is encouraged. Your vector should exclude 15, if used, it terminates the list prematurely; any following bit mappings will be ignored (it is the default/non category). The whole (A) vector/list passed to the macro is: - not strictly needed: 0-N bits are scanned, only N is needed in the macro interface to do this, not the whole list. - 0-N list allows juggling the bit->class map Identity map is preferred. 15 terminates list if used. (macro impl does this) That said, (A) is self-documenting; the explicit list is greppable, 'DRM_UT_*' provides lots of clues. Further, it could be upgraded, something like: _pick_sym_(DRM_UT_CORE, "mumble something useful about CORE debug") _pick_sym_(a,b) a // gives us what we need here _pick_help_(a,b) #a " : " b // mod-info fodder Signed-off-by: Jim Cromie --- include/linux/dynamic_debug.h | 50 +++ lib/dynamic_debug.c | 77 +++ 2 files changed, 127 insertions(+) diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index d4b48f3cc6e8..e83c4e36ad29 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -209,6 +209,10 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor, KERN_DEBUG, prefix_str, prefix_type, \ rowsize, groupsize, buf, len, ascii) +struct kernel_param; +int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp); +int param_get_dyndbg_classbits(char *buffer, const struct kernel_param *kp); + #else /* !CONFIG_DYNAMIC_DEBUG_CORE */ #include @@ -255,6 +259,52 @@ static inline int dynamic_debug_exec_queries(const char *query, const char *modn return 0; } +struct kernel_param;
[PATCH 01/13] dyndbg: fix static_branch manipulation
In https://lore.kernel.org/lkml/20211209150910.ga23...@axis.com/ Vincent's patch commented on, and worked around, a bug toggling static_branch's, when a 2nd PRINTK-ish flag was added. The bug results in a premature static_branch_disable when the 1st of 2 flags was disabled. The cited commit computed newflags, but then in the JUMP_LABEL block, did not use that result, but used just one of the terms in it. Using newflags instead made the code work properly. This is Vincents test-case, reduced. It needs the 2nd flag to work properly, but it's explanatory here. pt_test() { echo 5 > /sys/module/dynamic_debug/verbose site="module tcp" # just one callsite echo " $site =_ " > /proc/dynamic_debug/control # clear it # A B ~A ~B for flg in +T +p "-T #broke here" -p; do echo " $site $flg " > /proc/dynamic_debug/control done; # A B ~B ~A for flg in +T +p "-p #broke here" -T; do echo " $site $flg " > /proc/dynamic_debug/control done } pt_test Fixes: 84da83a6ffc0 dyndbg: combine flags & mask into a struct, simplify with it CC: vincent.whitchu...@axis.com CC: sta...@vger.kernel.org Signed-off-by: Jim Cromie --- lib/dynamic_debug.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index dd7f56af9aed..a56c1286ffa4 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -211,10 +211,11 @@ static int ddebug_change(const struct ddebug_query *query, continue; #ifdef CONFIG_JUMP_LABEL if (dp->flags & _DPRINTK_FLAGS_PRINT) { - if (!(modifiers->flags & _DPRINTK_FLAGS_PRINT)) + if (!(newflags & _DPRINTK_FLAGS_PRINT)) static_branch_disable(>key.dd_key_true); - } else if (modifiers->flags & _DPRINTK_FLAGS_PRINT) + } else if (newflags & _DPRINTK_FLAGS_PRINT) { static_branch_enable(>key.dd_key_true); + } #endif dp->flags = newflags; v4pr_info("changed %s:%d [%s]%s =%s\n", -- 2.35.1
[PATCH 02/13] dyndbg: add class_id field and query support
DRM defines/uses 10 enum drm_debug_category's to create exclusive classes of debug messages. To support this directly in dynamic-debug, add the following: - struct _ddebug.class_id:4 - 4 bits is enough - define _DPRINTK_SITE_UNCLASSED 15 - see below and the query support: - struct _ddebug_query.class_id - ddebug_parse_query- looks for "class" keyword, then calls.. - parse_class - accepts uint: 0-15, sets query.class_id and marker - vpr_info_dq - displays new field - ddebug_proc_show - append column with "cls:%d" if !UNCLASSED With the patch, this command enables current/unclassed callsites: #> echo drm class 15 +p > /proc/dynamic_debug/control parse_class() accepts 0 .. _DPRINTK_SITE_UNCLASSED, which allows the >control interface to explicitly manipulate unclassed callsites. After parsing keywords, ddebug_parse_query() sets .class_id=15, iff it wasnt explicitly set. This allows future classed/categorized callsites to be untouched by legacy (class unaware) queries. DEFINE_DYNAMIC_DEBUG_METADATA gets _CLS(cls,) suffix and arg, and initializes the new .class_id=cls field. The old name gets the default. Then, these _CLS(cls,...) modifications are repeated up through the stack of *dynamic_func_call* macros that use the METADATA initializer, so as to actually supply the category into it. NOTES: _DPRINTK_SITE_UNCLASSED: this symbol is used to initialize all existing/unclassed pr-debug callsites. Normally, the default would be zero, but DRM_UT_CORE "uses" that value, in the sense that 0 is exposed as a bit position in drm.debug. Using 15 allows identity mapping from category to class, avoiding fiddly offsets. CC: Rasmus Villemoes Signed-off-by: Jim Cromie fixup class-id preset fix2 --- .../admin-guide/dynamic-debug-howto.rst | 7 +++ include/linux/dynamic_debug.h | 54 ++- lib/dynamic_debug.c | 38 +++-- 3 files changed, 83 insertions(+), 16 deletions(-) diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst index a89cfa083155..8ef8d7dcd140 100644 --- a/Documentation/admin-guide/dynamic-debug-howto.rst +++ b/Documentation/admin-guide/dynamic-debug-howto.rst @@ -35,6 +35,7 @@ Dynamic debug has even more useful features: - line number (including ranges of line numbers) - module name - format string + - class number:0-15 * Provides a debugfs control file: ``/dynamic_debug/control`` which can be read to display the complete list of known debug @@ -143,6 +144,7 @@ against. Possible keywords are::: 'module' string | 'format' string | 'line' line-range +'class' integer:[0-15] line-range ::= lineno | '-'lineno | @@ -217,6 +219,11 @@ line line -1605 // the 1605 lines from line 1 to line 1605 line 1600- // all lines from line 1600 to the end of the file +class +This expects a single integer in range: 0-15. +15 is used/reserved for existing/unclassed callsites, +and is defaulted in unless specified to >control + The flags specification comprises a change operation followed by one or more flag characters. The change operation is one of the characters:: diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index dce631e678dd..d4b48f3cc6e8 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -6,6 +6,8 @@ #include #endif +#include + /* * An instance of this structure is created in a special * ELF section at every dynamic debug callsite. At runtime, @@ -21,6 +23,9 @@ struct _ddebug { const char *filename; const char *format; unsigned int lineno:18; +#define CLS_BITS 4 + unsigned int class_id:CLS_BITS; +#define _DPRINTK_SITE_UNCLASSED((1 << CLS_BITS) - 1) /* * The flags field controls the behaviour at the callsite. * The bits here are changed dynamically when the user @@ -87,7 +92,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor, const struct ib_device *ibdev, const char *fmt, ...); -#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \ +#define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt) \ static struct _ddebug __aligned(8) \ __section("__dyndbg") name = { \ .modname = KBUILD_MODNAME, \ @@ -96,8 +101,14 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor, .format = (fmt),\ .lineno = __LINE__, \ .flags = _DPRINTK_FLAGS_DEFAULT,\ + .class_id = cls,\ _DPRINTK_KEY_INIT
[PATCH 00/12] use dynamic-debug under drm.debug api
drm.debug api provides ~23 macros to issue 10 categories of debug messages, each enabled by a bit in /sys/module/drm/parameters/debug. drm_debug_enabled(category) tests these bits at runtime; while cheap individually, the costs accumulate. For CONFIG_DRM_USE_DYNAMIC_DEBUG=y, this patchset obsoletes those runtime tests (inside drm_*dbg) by wrapping the 2 fns in one of the dynamic_func_call* Factory macros. The config dependence is due to the .data footprint cost of the tables; AMDGPU has ~4k callsites, at 56 bytes each. This creates entries in /proc/dynamic_debug/control for each callsite, and each has .class_id = macros'-category. This, and a new query keyword, allow (1st): # 1=DRM_UT_KMS (iirc) #> echo "module drm class 1 +p > /proc/dynamic_debug/control Then equivalently: # except it also clears other flags #> echo 0x01 > /sys/module/drm/parameters/debug dyndbg: - fixes a bug in dyndbg static_key toggling, @stable cc'd - adds support for distinct classes to dyndbg (new,unused feature) - add DECLARE_DYNAMIC_DEBUG_CLASSBITS macro and callbacks to implement bitmap -> classid sysfs knob dyndbg: - drops exported fn: dynamic_debug_exec_queries() any potential users would just use macro, or a tweak on it. - improve info-msg to print both "old -> new" flags drm: - adapts drm to use that support (link category to class_id) - wraps drm_*dbg() in a dyndbg Factory macro to get NOOP optimized debugs this disconnects drm.debug sysfs knob - uses DECLARE_DYNAMIC_DEBUG_CLASSBITS macro this reconnects sysfs knob This could be -v12, but the focus and subject has wandered a bit, and patchwork CI had multiple different notions of the version. Noteworthy changes: - no tracefs stuff here, refocus split out already, needs maturation, more attention. its competing with a diet plan, to reduce 56 bytes/callsite. RFC. Previous drm.debug approach: - avoided drm_dbg & drm_devdbg by splicing in pr_debug & dev_dbg this preserved the optional decorations: module:function:line: - used DRM_UT_CORE => "drm:core:" prefix-string, cpp cat'd to formats this made sites selectable by matching to that format prefix This version: - .class_id is easier to explain, and no config/format-string diffs - wraps drm_dbg & drm_devdbg callsites for jumplabel enablement efficiency was original goal. - loses the optional decorations. drm has its own logmsg standards, doesnt need decorations slapped on later: could recast flags for drm specific decorations This is based on 5.17-rc4 Its also here: in (dd-drm branch) ghlinux-rohttps://github.com/jimc/linux.git (fetch) I'll push further fixes there as they come. Jim Cromie (13): dyndbg: fix static_branch manipulation @stable dyndbg: add class_id field and query support dyndbg: add DEFINE_DYNAMIC_DEBUG_CLASSBITS macro and callbacks dyndbg: drop EXPORTed dynamic_debug_exec_queries dyndbg: improve change-info to have old and new dyndbg: abstract dyndbg_site_is_printing drm_print: condense enum drm_debug_category drm_print: interpose drm_*dbg with forwarding macros drm_print: wrap drm_*_dbg in dyndbg jumplabel drm_print: refine drm_debug_enabled for dyndbg+jump-label drm_print: prefer bare printk KERN_DEBUG on generic fn drm_print: add _ddebug desc to drm_*dbg prototypes drm_print: use DEFINE_DYNAMIC_DEBUG_CLASSBITS for drm.debug .../admin-guide/dynamic-debug-howto.rst | 7 + drivers/gpu/drm/Kconfig | 12 ++ drivers/gpu/drm/Makefile | 2 + drivers/gpu/drm/drm_print.c | 56 --- include/drm/drm_print.h | 80 +++--- include/linux/dynamic_debug.h | 113 +++--- lib/dynamic_debug.c | 140 ++ 7 files changed, 323 insertions(+), 87 deletions(-) -- 2.35.1
[PATCH 2/3] drm/msm/dpu: fix error handling around dpu_hw_vbif_init
Using IS_ERR_OR_NULL() together with PTR_ERR() is a typical mistake. If the value is NULL, then the function will return 0 instead of a proper return code. Moreover dpu_hw_vbif_init() function can not return NULL. So, replace corresponding IS_ERR_OR_NULL() call with IS_ERR(). Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 81a35c8d62e7..f8f1bf3b511d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1102,10 +1102,8 @@ static int dpu_kms_hw_init(struct msm_kms *kms) dpu_kms->hw_vbif[vbif_idx] = dpu_hw_vbif_init(vbif_idx, dpu_kms->vbif[vbif_idx], dpu_kms->catalog); - if (IS_ERR_OR_NULL(dpu_kms->hw_vbif[vbif_idx])) { + if (IS_ERR(dpu_kms->hw_vbif[vbif_idx])) { rc = PTR_ERR(dpu_kms->hw_vbif[vbif_idx]); - if (!dpu_kms->hw_vbif[vbif_idx]) - rc = -EINVAL; DPU_ERROR("failed to init vbif %d: %d\n", vbif_idx, rc); dpu_kms->hw_vbif[vbif_idx] = NULL; goto power_error; -- 2.34.1
[PATCH 3/3] drm/msm/dpu: drop VBIF indices
We do not expect to have other VBIFs. Drop VBIF_n indices and always use VBIF_RT and VBIF_NRT. Signed-off-by: Dmitry Baryshkov --- .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 4 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 6 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c | 36 --- 3 files changed, 28 insertions(+), 18 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 aa4d20762ccb..dbb853042aa0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -1115,7 +1115,7 @@ static const struct dpu_vbif_dynamic_ot_cfg msm8998_ot_rdwr_cfg[] = { static const struct dpu_vbif_cfg msm8998_vbif[] = { { - .name = "vbif_0", .id = VBIF_0, + .name = "vbif_rt", .id = VBIF_RT, .base = 0, .len = 0x1040, .default_ot_rd_limit = 32, .default_ot_wr_limit = 32, @@ -1144,7 +1144,7 @@ static const struct dpu_vbif_cfg msm8998_vbif[] = { static const struct dpu_vbif_cfg sdm845_vbif[] = { { - .name = "vbif_0", .id = VBIF_0, + .name = "vbif_rt", .id = VBIF_RT, .base = 0, .len = 0x1040, .features = BIT(DPU_VBIF_QOS_REMAP), .xin_halt_timeout = 0x4000, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h index bb9ceadeb0bb..598c201ae50d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h @@ -254,11 +254,9 @@ enum dpu_wd_timer { }; enum dpu_vbif { - VBIF_0, - VBIF_1, + VBIF_RT, + VBIF_NRT, VBIF_MAX, - VBIF_RT = VBIF_0, - VBIF_NRT = VBIF_1 }; /** diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c index cbbf77b17fc3..c011d4ab6acc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c @@ -19,6 +19,18 @@ static struct dpu_hw_vbif *dpu_get_vbif(struct dpu_kms *dpu_kms, enum dpu_vbif v return NULL; } +static const char *dpu_vbif_name(enum dpu_vbif idx) +{ + switch (idx) { + case VBIF_RT: + return "VBIF_RT"; + case VBIF_NRT: + return "VBIF_NRT"; + default: + return "??"; + } +} + /** * _dpu_vbif_wait_for_xin_halt - wait for the xin to halt * @vbif: Pointer to hardware vbif driver @@ -50,12 +62,12 @@ static int _dpu_vbif_wait_for_xin_halt(struct dpu_hw_vbif *vbif, u32 xin_id) if (!status) { rc = -ETIMEDOUT; - DPU_ERROR("VBIF %d client %d not halting. TIMEDOUT.\n", - vbif->idx - VBIF_0, xin_id); + DPU_ERROR("%s client %d not halting. TIMEDOUT.\n", + dpu_vbif_name(vbif->idx), xin_id); } else { rc = 0; - DRM_DEBUG_ATOMIC("VBIF %d client %d is halted\n", - vbif->idx - VBIF_0, xin_id); + DRM_DEBUG_ATOMIC("%s client %d is halted\n", + dpu_vbif_name(vbif->idx), xin_id); } return rc; @@ -95,8 +107,8 @@ static void _dpu_vbif_apply_dynamic_ot_limit(struct dpu_hw_vbif *vbif, } } - DRM_DEBUG_ATOMIC("vbif:%d xin:%d w:%d h:%d fps:%d pps:%llu ot:%u\n", - vbif->idx - VBIF_0, params->xin_id, + DRM_DEBUG_ATOMIC("%s xin:%d w:%d h:%d fps:%d pps:%llu ot:%u\n", + dpu_vbif_name(vbif->idx), params->xin_id, params->width, params->height, params->frame_rate, pps, *ot_lim); } @@ -141,8 +153,8 @@ static u32 _dpu_vbif_get_ot_limit(struct dpu_hw_vbif *vbif, } exit: - DRM_DEBUG_ATOMIC("vbif:%d xin:%d ot_lim:%d\n", - vbif->idx - VBIF_0, params->xin_id, ot_lim); + DRM_DEBUG_ATOMIC("%s xin:%d ot_lim:%d\n", + dpu_vbif_name(vbif->idx), params->xin_id, ot_lim); return ot_lim; } @@ -242,8 +254,8 @@ void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms, forced_on = mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, true); for (i = 0; i < qos_tbl->npriority_lvl; i++) { - DRM_DEBUG_ATOMIC("vbif:%d xin:%d lvl:%d/%d\n", - params->vbif_idx, params->xin_id, i, + DRM_DEBUG_ATOMIC("%s xin:%d lvl:%d/%d\n", + dpu_vbif_name(params->vbif_idx), params->xin_id, i, qos_tbl->priority_lvl[i]); vbif->ops.set_qos_remap(vbif, params->xin_id, i, qos_tbl->priority_lvl[i]); @@ -263,8 +275,8 @@ void dpu_vbif_clear_errors(struct dpu_kms *dpu_kms) if (vbif && vbif->ops.clear_errors) { vbif->ops.clear_errors(vbif, , );
[PATCH 1/3] drm/msm/dpu: index dpu_kms->hw_vbif using vbif_idx
Remove loops over hw_vbif. Instead always VBIF's idx as an index in the array. This fixes an error in dpu_kms_hw_init(), where we fill dpu_kms->hw_vbif[i], but check for an error pointer at dpu_kms->hw_vbif[vbif_idx]. Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support") Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 10 drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c | 29 +++- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index d0653a9ec694..81a35c8d62e7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -790,11 +790,9 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms) _dpu_kms_mmu_destroy(dpu_kms); if (dpu_kms->catalog) { - for (i = 0; i < dpu_kms->catalog->vbif_count; i++) { - u32 vbif_idx = dpu_kms->catalog->vbif[i].id; - - if ((vbif_idx < VBIF_MAX) && dpu_kms->hw_vbif[vbif_idx]) - dpu_hw_vbif_destroy(dpu_kms->hw_vbif[vbif_idx]); + for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) { + if (dpu_kms->hw_vbif[i]) + dpu_hw_vbif_destroy(dpu_kms->hw_vbif[i]); } } @@ -1102,7 +1100,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) for (i = 0; i < dpu_kms->catalog->vbif_count; i++) { u32 vbif_idx = dpu_kms->catalog->vbif[i].id; - dpu_kms->hw_vbif[i] = dpu_hw_vbif_init(vbif_idx, + dpu_kms->hw_vbif[vbif_idx] = dpu_hw_vbif_init(vbif_idx, dpu_kms->vbif[vbif_idx], dpu_kms->catalog); if (IS_ERR_OR_NULL(dpu_kms->hw_vbif[vbif_idx])) { rc = PTR_ERR(dpu_kms->hw_vbif[vbif_idx]); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c index 21d20373eb8b..cbbf77b17fc3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c @@ -11,6 +11,14 @@ #include "dpu_hw_vbif.h" #include "dpu_trace.h" +static struct dpu_hw_vbif *dpu_get_vbif(struct dpu_kms *dpu_kms, enum dpu_vbif vbif_idx) +{ + if (vbif_idx > ARRAY_SIZE(dpu_kms->hw_vbif)) + return dpu_kms->hw_vbif[vbif_idx]; + + return NULL; +} + /** * _dpu_vbif_wait_for_xin_halt - wait for the xin to halt * @vbif: Pointer to hardware vbif driver @@ -148,20 +156,15 @@ static u32 _dpu_vbif_get_ot_limit(struct dpu_hw_vbif *vbif, void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms, struct dpu_vbif_set_ot_params *params) { - struct dpu_hw_vbif *vbif = NULL; + struct dpu_hw_vbif *vbif; struct dpu_hw_mdp *mdp; bool forced_on = false; u32 ot_lim; - int ret, i; + int ret; mdp = dpu_kms->hw_mdp; - for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) { - if (dpu_kms->hw_vbif[i] && - dpu_kms->hw_vbif[i]->idx == params->vbif_idx) - vbif = dpu_kms->hw_vbif[i]; - } - + vbif = dpu_get_vbif(dpu_kms, params->vbif_idx); if (!vbif || !mdp) { DRM_DEBUG_ATOMIC("invalid arguments vbif %d mdp %d\n", vbif != NULL, mdp != NULL); @@ -204,7 +207,7 @@ void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms, void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms, struct dpu_vbif_set_qos_params *params) { - struct dpu_hw_vbif *vbif = NULL; + struct dpu_hw_vbif *vbif; struct dpu_hw_mdp *mdp; bool forced_on = false; const struct dpu_vbif_qos_tbl *qos_tbl; @@ -216,13 +219,7 @@ void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms, } mdp = dpu_kms->hw_mdp; - for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) { - if (dpu_kms->hw_vbif[i] && - dpu_kms->hw_vbif[i]->idx == params->vbif_idx) { - vbif = dpu_kms->hw_vbif[i]; - break; - } - } + vbif = dpu_get_vbif(dpu_kms, params->vbif_idx); if (!vbif || !vbif->cap) { DPU_ERROR("invalid vbif %d\n", params->vbif_idx); -- 2.34.1
Re: [Freedreno] [REPOST PATCH v4 13/13] drm/msm/dsi: Add support for DSC configuration
On 2/10/2022 2:34 AM, 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: Dmitry Baryshkov Signed-off-by: Vinod Koul --- drivers/gpu/drm/msm/dsi/dsi.xml.h | 10 +++ drivers/gpu/drm/msm/dsi/dsi_host.c | 109 - 2 files changed, 118 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h index 49b551ad1bff..c1c85df58c4b 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.xml.h +++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h @@ -706,4 +706,14 @@ static inline uint32_t DSI_VERSION_MAJOR(uint32_t val) #define REG_DSI_CPHY_MODE_CTRL 0x02d4 +#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL 0x029c + +#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 + This file should not be edited manually. The updates have to be generated using the headergen tool. #endif /* DSI_XML */ diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 438c80750682..3d8d5a1daaa3 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -908,6 +908,20 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, dsi_write(msm_host, REG_DSI_CPHY_MODE_CTRL, BIT(0)); } +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; + } + + 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_bonded_dsi) { struct drm_display_mode *mode = msm_host->mode; @@ -940,7 +954,68 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_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; + 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); + + dsc->drm->slice_count = 1; Why is this hard-coded to 1 here? Am i missing something? I think I need another day to look into these calculations. + 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); + dsc->bytes_per_pkt = dsc->bytes_in_slice * dsc->drm->slice_count; + dsc->pkt_per_line = slice_per_intf / dsc->drm->slice_count; + + reg = dsc->bytes_per_pkt << 16; + reg |= (0x0b << 8);/* dtype of compressed image */ + + /* pkt_per_line: +* 0 == 1 pkt +* 1 == 2 pkt +* 2 == 4 pkt +* 3 pkt is not supported +* above translates to ffs() - 1 +
Re: [REPOST PATCH v4 11/13] drm/msm/disp/dpu1: Add DSC support in RM
On 2/10/2022 2:34 AM, Vinod Koul wrote: This add the bits in RM to enable the DSC blocks Reviewed-by: Dmitry Baryshkov Signed-off-by: Vinod Koul Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 56 + drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 1 + 3 files changed, 58 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 2d385b4b7f5e..8f2fb667b05c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -146,6 +146,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 dsc_to_enc_id[DSC_MAX - DSC_0]; }; struct dpu_global_state diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index f9c83d6e427a..fbb24bb2b998 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -11,6 +11,7 @@ #include "dpu_hw_intf.h" #include "dpu_hw_dspp.h" #include "dpu_hw_merge3d.h" +#include "dpu_hw_dsc.h" #include "dpu_encoder.h" #include "dpu_trace.h" @@ -75,6 +76,14 @@ int dpu_rm_destroy(struct dpu_rm *rm) dpu_hw_intf_destroy(hw); } } + for (i = 0; i < ARRAY_SIZE(rm->dsc_blks); i++) { + struct dpu_hw_dsc *hw; + + if (rm->dsc_blks[i]) { + hw = to_dpu_hw_dsc(rm->dsc_blks[i]); + dpu_hw_dsc_destroy(hw); + } + } return 0; } @@ -221,6 +230,19 @@ int dpu_rm_init(struct dpu_rm *rm, rm->dspp_blks[dspp->id - DSPP_0] = >base; } + for (i = 0; i < cat->dsc_count; i++) { + struct dpu_hw_dsc *hw; + const struct dpu_dsc_cfg *dsc = >dsc[i]; + + hw = dpu_hw_dsc_init(dsc->id, mmio, cat); + if (IS_ERR_OR_NULL(hw)) { + rc = PTR_ERR(hw); + DPU_ERROR("failed dsc object creation: err %d\n", rc); + goto fail; + } + rm->dsc_blks[dsc->id - DSC_0] = >base; + } + return 0; fail: @@ -476,6 +498,7 @@ static int _dpu_rm_reserve_intf( } global_state->intf_to_enc_id[idx] = enc_id; + return 0; } @@ -500,6 +523,28 @@ static int _dpu_rm_reserve_intf_related_hw( return ret; } +static int _dpu_rm_reserve_dsc(struct dpu_rm *rm, + struct dpu_global_state *global_state, + struct drm_encoder *enc, + const struct msm_display_topology *top) +{ + int num_dsc = top->num_dsc; + int i; + + /* check if DSC required are allocated or not */ + for (i = 0; i < num_dsc; i++) { + if (global_state->dsc_to_enc_id[i]) { + DPU_ERROR("DSC %d is already allocated\n", i); + return -EIO; + } + } + + for (i = 0; i < num_dsc; i++) + global_state->dsc_to_enc_id[i] = enc->base.id; + + return 0; +} + static int _dpu_rm_make_reservation( struct dpu_rm *rm, struct dpu_global_state *global_state, @@ -526,6 +571,10 @@ static int _dpu_rm_make_reservation( if (ret) return ret; + ret = _dpu_rm_reserve_dsc(rm, global_state, enc, >topology); + if (ret) + return ret; + return ret; } @@ -567,6 +616,8 @@ void dpu_rm_release(struct dpu_global_state *global_state, ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id); _dpu_rm_clear_mapping(global_state->intf_to_enc_id, ARRAY_SIZE(global_state->intf_to_enc_id), enc->base.id); + _dpu_rm_clear_mapping(global_state->dsc_to_enc_id, + ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id); } int dpu_rm_reserve( @@ -640,6 +691,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm, hw_to_enc_id = global_state->dspp_to_enc_id; max_blks = ARRAY_SIZE(rm->dspp_blks); break; + case DPU_HW_BLK_DSC: + hw_blks = rm->dsc_blks; + hw_to_enc_id = global_state->dsc_to_enc_id; + max_blks = ARRAY_SIZE(rm->dsc_blks); + break; default: DPU_ERROR("blk type %d not managed by rm\n", type); return 0; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h index 1f12c8d5b8aa..278d2a510b80 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h @@ -30,6 +30,7 @@ struct dpu_rm { struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0];
Re: [REPOST PATCH v4 12/13] drm/msm/dsi: add mode valid callback for dsi_mgr
On 2/10/2022 2:34 AM, Vinod Koul wrote: Add a mode valid callback for dsi_mgr for checking mode being valid in case of DSC. For DSC the height and width needs to be multiple of slice, so we check that here Reviewed-by: Dmitry Baryshkov Signed-off-by: Vinod Koul Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/dsi/dsi.h | 2 ++ drivers/gpu/drm/msm/dsi/dsi_host.c| 26 ++ drivers/gpu/drm/msm/dsi/dsi_manager.c | 12 3 files changed, 40 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 16cd9b2fce86..580a1e6358bf 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -114,6 +114,8 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host, 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); +enum drm_mode_status msm_dsi_host_check_dsc(struct mipi_dsi_host *host, + const struct drm_display_mode *mode); struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host); 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); diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 7e9913eff724..438c80750682 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -2552,6 +2552,32 @@ int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host, return 0; } +enum drm_mode_status msm_dsi_host_check_dsc(struct mipi_dsi_host *host, + const struct drm_display_mode *mode) +{ + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + struct msm_display_dsc_config *dsc = msm_host->dsc; + int pic_width = mode->hdisplay; + int pic_height = mode->vdisplay; + + if (!msm_host->dsc) + return MODE_OK; + + if (pic_width % dsc->drm->slice_width) { + pr_err("DSI: pic_width %d has to be multiple of slice %d\n", + pic_width, dsc->drm->slice_width); + return MODE_H_ILLEGAL; + } + + if (pic_height % dsc->drm->slice_height) { + pr_err("DSI: pic_height %d has to be multiple of slice %d\n", + pic_height, dsc->drm->slice_height); + return MODE_V_ILLEGAL; + } + + return MODE_OK; +} + struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host) { return of_drm_find_panel(to_msm_dsi_host(host)->device_node); diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index f19bae475c96..e7f6cc88f7a4 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -575,6 +575,17 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge, msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode); } +static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + int id = dsi_mgr_bridge_get_id(bridge); + struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); + struct mipi_dsi_host *host = msm_dsi->host; + + return msm_dsi_host_check_dsc(host, mode); +} + static const struct drm_connector_funcs dsi_mgr_connector_funcs = { .detect = dsi_mgr_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, @@ -596,6 +607,7 @@ static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = { .disable = dsi_mgr_bridge_disable, .post_disable = dsi_mgr_bridge_post_disable, .mode_set = dsi_mgr_bridge_mode_set, + .mode_valid = dsi_mgr_bridge_mode_valid, }; /* initialize connector when we're connected to a drm_panel */
Re: [REPOST PATCH v4 11/13] drm/msm/disp/dpu1: Add DSC support in RM
On 2/10/2022 2:34 AM, Vinod Koul wrote: This add the bits in RM to enable the DSC blocks Reviewed-by: Dmitry Baryshkov Signed-off-by: Vinod Koul --Reviewed-by: Abhinav Kumar drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 56 + drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 1 + 3 files changed, 58 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 2d385b4b7f5e..8f2fb667b05c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -146,6 +146,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 dsc_to_enc_id[DSC_MAX - DSC_0]; }; struct dpu_global_state diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index f9c83d6e427a..fbb24bb2b998 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -11,6 +11,7 @@ #include "dpu_hw_intf.h" #include "dpu_hw_dspp.h" #include "dpu_hw_merge3d.h" +#include "dpu_hw_dsc.h" #include "dpu_encoder.h" #include "dpu_trace.h" @@ -75,6 +76,14 @@ int dpu_rm_destroy(struct dpu_rm *rm) dpu_hw_intf_destroy(hw); } } + for (i = 0; i < ARRAY_SIZE(rm->dsc_blks); i++) { + struct dpu_hw_dsc *hw; + + if (rm->dsc_blks[i]) { + hw = to_dpu_hw_dsc(rm->dsc_blks[i]); + dpu_hw_dsc_destroy(hw); + } + } return 0; } @@ -221,6 +230,19 @@ int dpu_rm_init(struct dpu_rm *rm, rm->dspp_blks[dspp->id - DSPP_0] = >base; } + for (i = 0; i < cat->dsc_count; i++) { + struct dpu_hw_dsc *hw; + const struct dpu_dsc_cfg *dsc = >dsc[i]; + + hw = dpu_hw_dsc_init(dsc->id, mmio, cat); + if (IS_ERR_OR_NULL(hw)) { + rc = PTR_ERR(hw); + DPU_ERROR("failed dsc object creation: err %d\n", rc); + goto fail; + } + rm->dsc_blks[dsc->id - DSC_0] = >base; + } + return 0; fail: @@ -476,6 +498,7 @@ static int _dpu_rm_reserve_intf( } global_state->intf_to_enc_id[idx] = enc_id; + return 0; } @@ -500,6 +523,28 @@ static int _dpu_rm_reserve_intf_related_hw( return ret; } +static int _dpu_rm_reserve_dsc(struct dpu_rm *rm, + struct dpu_global_state *global_state, + struct drm_encoder *enc, + const struct msm_display_topology *top) +{ + int num_dsc = top->num_dsc; + int i; + + /* check if DSC required are allocated or not */ + for (i = 0; i < num_dsc; i++) { + if (global_state->dsc_to_enc_id[i]) { + DPU_ERROR("DSC %d is already allocated\n", i); + return -EIO; + } + } + + for (i = 0; i < num_dsc; i++) + global_state->dsc_to_enc_id[i] = enc->base.id; + + return 0; +} + static int _dpu_rm_make_reservation( struct dpu_rm *rm, struct dpu_global_state *global_state, @@ -526,6 +571,10 @@ static int _dpu_rm_make_reservation( if (ret) return ret; + ret = _dpu_rm_reserve_dsc(rm, global_state, enc, >topology); + if (ret) + return ret; + return ret; } @@ -567,6 +616,8 @@ void dpu_rm_release(struct dpu_global_state *global_state, ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id); _dpu_rm_clear_mapping(global_state->intf_to_enc_id, ARRAY_SIZE(global_state->intf_to_enc_id), enc->base.id); + _dpu_rm_clear_mapping(global_state->dsc_to_enc_id, + ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id); } int dpu_rm_reserve( @@ -640,6 +691,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm, hw_to_enc_id = global_state->dspp_to_enc_id; max_blks = ARRAY_SIZE(rm->dspp_blks); break; + case DPU_HW_BLK_DSC: + hw_blks = rm->dsc_blks; + hw_to_enc_id = global_state->dsc_to_enc_id; + max_blks = ARRAY_SIZE(rm->dsc_blks); + break; default: DPU_ERROR("blk type %d not managed by rm\n", type); return 0; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h index 1f12c8d5b8aa..278d2a510b80 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h @@ -30,6 +30,7 @@ struct dpu_rm { struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0];
Re: [REPOST PATCH v4 09/13] drm/msm: Add missing structure documentation
On 2/10/2022 2:34 AM, Vinod Koul wrote: Somehow documentation for dspp was missed, so add that Signed-off-by: Vinod Koul Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/msm_drv.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index e7a312edfe67..6425a42e997c 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -102,6 +102,7 @@ enum msm_event_wait { * @num_lm: number of layer mixers used * @num_enc: number of compression encoder blocks used * @num_intf: number of interfaces the panel is mounted on + * @num_dspp: number of dspp blocks used */ struct msm_display_topology { u32 num_lm;
Re: [REPOST PATCH v4 08/13] drm/msm/disp/dpu1: Don't use DSC with mode_3d
On 2/10/2022 2:34 AM, 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() to detect dsc enabled and pass this to .setup_intf_cfg() Signed-off-by: Vinod Koul We should not use 3D mux only when we use DSC merge topology. I agree that today we use only 2-2-1 topology for DSC which means its using DSC merge. But generalizing that 3D mux should not be used for DSC is not right. You can detect DSC merge by checking if there are two encoders and one interface in the topology and if so, you can disable 3D mux. --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 4 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 4 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 7 ++- 3 files changed, 14 insertions(+), 1 deletion(-) 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 34a6940d12c5..ed37a4c21596 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 @@ -70,6 +70,10 @@ 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(phys_enc); + if (intf_cfg.dsc) + intf_cfg.mode_3d = 0; + ctl->ops.setup_intf_cfg(ctl, _cfg); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index ddd9d89cd456..218009855fca 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -284,6 +284,10 @@ static void dpu_encoder_phys_vid_setup_timing_engine( intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_VID; intf_cfg.stream_sel = 0; /* Don't care value for video mode */ intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); + intf_cfg.dsc = dpu_encoder_helper_get_dsc(phys_enc); + if (intf_cfg.dsc) + intf_cfg.mode_3d = 0; + if (phys_enc->hw_pp->merge_3d) intf_cfg.merge_3d = phys_enc->hw_pp->merge_3d->idx; 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 49659165cea8..6d5268b7da90 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -536,7 +536,12 @@ 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 and complain */ + if (cfg->mode_3d && cfg->dsc) + pr_err("DPU1: DSC and Merge 3D both are set!! it may not work\n"); + + /* set merge only when dsc is not set */ + if (cfg->mode_3d && !cfg->dsc) { intf_cfg |= BIT(19); intf_cfg |= (cfg->mode_3d - 0x1) << 20; }
Re: [PATCH] drm/bridge: anx7625: Fix release wrong workqueue
On Thu, Feb 17, 2022 at 10:45 AM Xin Ji wrote: > > From: Xin Ji > > If "hdcp_workqueue" exist, must release "hdcp_workqueue", > not "workqueue". > > Fixes: cd1637c7e480 ("drm/bridge: anx7625: add HDCP support") > Signed-off-by: Xin Ji > --- Reviewed-by: Hsin-Yi Wang This fixes an issue that the driver will crash during unbind. > drivers/gpu/drm/bridge/analogix/anx7625.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c > b/drivers/gpu/drm/bridge/analogix/anx7625.c > index 633618bafd75..9aab879a8851 100644 > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c > @@ -2736,8 +2736,8 @@ static int anx7625_i2c_remove(struct i2c_client *client) > > if (platform->hdcp_workqueue) { > cancel_delayed_work(>hdcp_work); > - flush_workqueue(platform->workqueue); > - destroy_workqueue(platform->workqueue); > + flush_workqueue(platform->hdcp_workqueue); > + destroy_workqueue(platform->hdcp_workqueue); > } > > if (!platform->pdata.low_power_mode) > -- > 2.25.1 >
[PATCH] drm/bridge: anx7625: Fix release wrong workqueue
From: Xin Ji If "hdcp_workqueue" exist, must release "hdcp_workqueue", not "workqueue". Fixes: cd1637c7e480 ("drm/bridge: anx7625: add HDCP support") Signed-off-by: Xin Ji --- drivers/gpu/drm/bridge/analogix/anx7625.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 633618bafd75..9aab879a8851 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -2736,8 +2736,8 @@ static int anx7625_i2c_remove(struct i2c_client *client) if (platform->hdcp_workqueue) { cancel_delayed_work(>hdcp_work); - flush_workqueue(platform->workqueue); - destroy_workqueue(platform->workqueue); + flush_workqueue(platform->hdcp_workqueue); + destroy_workqueue(platform->hdcp_workqueue); } if (!platform->pdata.low_power_mode) -- 2.25.1
Re: [PATCH v3 2/2] drm/msm/dpu: Add SC8180x to hw catalog
On 17/02/2022 04:21, Bjorn Andersson wrote: From: Rob Clark Add SC8180x to the hardware catalog, for initial support for the platform. Due to limitations in the DP driver only one of the four DP interfaces is left enabled. The SC8180x platform supports the newly added DPU_INTF_WIDEBUS flag and the Windows-on-Snapdragon bootloader leaves the widebus bit set, so this is flagged appropriately to ensure widebus is disabled - for now. Signed-off-by: Rob Clark [bjorn: Reworked intf and irq definitions] Signed-off-by: Bjorn Andersson Reviewed-by: Dmitry Baryshkov --- Changes since v2: - Dropped the extra element in danger_lut_tbl .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 129 ++ .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h| 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 1 + drivers/gpu/drm/msm/msm_drv.c | 1 + 4 files changed, 132 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 aa75991903a6..db72eca343d7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -90,6 +90,17 @@ BIT(MDP_INTF3_INTR) | \ BIT(MDP_INTF4_INTR)) +#define IRQ_SC8180X_MASK (BIT(MDP_SSPP_TOP0_INTR) | \ + BIT(MDP_SSPP_TOP0_INTR2) | \ + BIT(MDP_SSPP_TOP0_HIST_INTR) | \ + BIT(MDP_INTF0_INTR) | \ + BIT(MDP_INTF1_INTR) | \ + BIT(MDP_INTF2_INTR) | \ + BIT(MDP_INTF3_INTR) | \ + BIT(MDP_INTF4_INTR) | \ + BIT(MDP_INTF5_INTR) | \ + BIT(MDP_AD4_0_INTR) | \ + BIT(MDP_AD4_1_INTR)) #define DEFAULT_PIXEL_RAM_SIZE (50 * 1024) #define DEFAULT_DPU_LINE_WIDTH2048 @@ -225,6 +236,22 @@ static const struct dpu_caps sm8150_dpu_caps = { .max_vdeci_exp = MAX_VERT_DECIMATION, }; +static const struct dpu_caps sc8180x_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 */ + .ubwc_version = DPU_HW_UBWC_VER_30, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = 4096, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, + .max_hdeci_exp = MAX_HORZ_DECIMATION, + .max_vdeci_exp = MAX_VERT_DECIMATION, +}; + static const struct dpu_caps sm8250_dpu_caps = { .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, @@ -293,6 +320,31 @@ static const struct dpu_mdp_cfg sc7180_mdp[] = { }, }; +static const struct dpu_mdp_cfg sc8180x_mdp[] = { + { + .name = "top_0", .id = MDP_TOP, + .base = 0x0, .len = 0x45C, + .features = 0, + .highest_bank_bit = 0x3, + .clk_ctrls[DPU_CLK_CTRL_VIG0] = { + .reg_off = 0x2AC, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG1] = { + .reg_off = 0x2B4, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG2] = { + .reg_off = 0x2BC, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG3] = { + .reg_off = 0x2C4, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_DMA0] = { + .reg_off = 0x2AC, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_DMA1] = { + .reg_off = 0x2B4, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { + .reg_off = 0x2BC, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { + .reg_off = 0x2C4, .bit_off = 8}, + }, +}; + static const struct dpu_mdp_cfg sm8250_mdp[] = { { .name = "top_0", .id = MDP_TOP, @@ -861,6 +913,16 @@ static const struct dpu_intf_cfg sc7280_intf[] = { INTF_BLK("intf_5", INTF_5, 0x39000, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 22, 23), }; +static const struct dpu_intf_cfg sc8180x_intf[] = { + 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), + INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 24, INTF_SC7180_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_SC7180_MASK, MDP_SSPP_TOP0_INTR, 30, 31), + INTF_BLK("intf_4", INTF_4, 0x6C000, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 20, 21), +
[PATCH v3 2/2] drm/msm/dpu: Add SC8180x to hw catalog
From: Rob Clark Add SC8180x to the hardware catalog, for initial support for the platform. Due to limitations in the DP driver only one of the four DP interfaces is left enabled. The SC8180x platform supports the newly added DPU_INTF_WIDEBUS flag and the Windows-on-Snapdragon bootloader leaves the widebus bit set, so this is flagged appropriately to ensure widebus is disabled - for now. Signed-off-by: Rob Clark [bjorn: Reworked intf and irq definitions] Signed-off-by: Bjorn Andersson --- Changes since v2: - Dropped the extra element in danger_lut_tbl .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 129 ++ .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h| 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 1 + drivers/gpu/drm/msm/msm_drv.c | 1 + 4 files changed, 132 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 aa75991903a6..db72eca343d7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -90,6 +90,17 @@ BIT(MDP_INTF3_INTR) | \ BIT(MDP_INTF4_INTR)) +#define IRQ_SC8180X_MASK (BIT(MDP_SSPP_TOP0_INTR) | \ + BIT(MDP_SSPP_TOP0_INTR2) | \ + BIT(MDP_SSPP_TOP0_HIST_INTR) | \ + BIT(MDP_INTF0_INTR) | \ + BIT(MDP_INTF1_INTR) | \ + BIT(MDP_INTF2_INTR) | \ + BIT(MDP_INTF3_INTR) | \ + BIT(MDP_INTF4_INTR) | \ + BIT(MDP_INTF5_INTR) | \ + BIT(MDP_AD4_0_INTR) | \ + BIT(MDP_AD4_1_INTR)) #define DEFAULT_PIXEL_RAM_SIZE (50 * 1024) #define DEFAULT_DPU_LINE_WIDTH 2048 @@ -225,6 +236,22 @@ static const struct dpu_caps sm8150_dpu_caps = { .max_vdeci_exp = MAX_VERT_DECIMATION, }; +static const struct dpu_caps sc8180x_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 */ + .ubwc_version = DPU_HW_UBWC_VER_30, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = 4096, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, + .max_hdeci_exp = MAX_HORZ_DECIMATION, + .max_vdeci_exp = MAX_VERT_DECIMATION, +}; + static const struct dpu_caps sm8250_dpu_caps = { .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, @@ -293,6 +320,31 @@ static const struct dpu_mdp_cfg sc7180_mdp[] = { }, }; +static const struct dpu_mdp_cfg sc8180x_mdp[] = { + { + .name = "top_0", .id = MDP_TOP, + .base = 0x0, .len = 0x45C, + .features = 0, + .highest_bank_bit = 0x3, + .clk_ctrls[DPU_CLK_CTRL_VIG0] = { + .reg_off = 0x2AC, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG1] = { + .reg_off = 0x2B4, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG2] = { + .reg_off = 0x2BC, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG3] = { + .reg_off = 0x2C4, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_DMA0] = { + .reg_off = 0x2AC, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_DMA1] = { + .reg_off = 0x2B4, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { + .reg_off = 0x2BC, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { + .reg_off = 0x2C4, .bit_off = 8}, + }, +}; + static const struct dpu_mdp_cfg sm8250_mdp[] = { { .name = "top_0", .id = MDP_TOP, @@ -861,6 +913,16 @@ static const struct dpu_intf_cfg sc7280_intf[] = { INTF_BLK("intf_5", INTF_5, 0x39000, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 22, 23), }; +static const struct dpu_intf_cfg sc8180x_intf[] = { + 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), + INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 24, INTF_SC7180_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_SC7180_MASK, MDP_SSPP_TOP0_INTR, 30, 31), + INTF_BLK("intf_4", INTF_4, 0x6C000, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 20, 21), + INTF_BLK("intf_5", INTF_5, 0x6C800, INTF_DP, MSM_DP_CONTROLLER_2, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 22,
[PATCH v3 1/2] drm/msm/dpu: Add INTF_5 interrupts
SC8180x has the eDP controller wired up to INTF_5, so add the interrupt register block for this interface to the list. Signed-off-by: Bjorn Andersson --- Changes since v2: - None drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 6 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 1 + 2 files changed, 7 insertions(+) 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 a77a5eaa78ad..dd2161e7bdb6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -23,6 +23,7 @@ #define MDP_INTF_2_OFF 0x6B000 #define MDP_INTF_3_OFF 0x6B800 #define MDP_INTF_4_OFF 0x6C000 +#define MDP_INTF_5_OFF 0x6C800 #define MDP_AD4_0_OFF 0x7C000 #define MDP_AD4_1_OFF 0x7D000 #define MDP_AD4_INTR_EN_OFF0x41c @@ -93,6 +94,11 @@ static const struct dpu_intr_reg dpu_intr_set[] = { MDP_INTF_4_OFF+INTF_INTR_EN, MDP_INTF_4_OFF+INTF_INTR_STATUS }, + { + MDP_INTF_5_OFF+INTF_INTR_CLEAR, + MDP_INTF_5_OFF+INTF_INTR_EN, + MDP_INTF_5_OFF+INTF_INTR_STATUS + }, { MDP_AD4_0_OFF + MDP_AD4_INTR_CLEAR_OFF, MDP_AD4_0_OFF + MDP_AD4_INTR_EN_OFF, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h index 1ab75cccd145..37379966d8ec 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h @@ -22,6 +22,7 @@ enum dpu_hw_intr_reg { MDP_INTF2_INTR, MDP_INTF3_INTR, MDP_INTF4_INTR, + MDP_INTF5_INTR, MDP_AD4_0_INTR, MDP_AD4_1_INTR, MDP_INTF0_7xxx_INTR, -- 2.33.1
Re: [PATCH 5/6] drm/msm/dpu: remove struct dpu_encoder_irq
On 16/02/2022 05:22, Stephen Boyd wrote: Quoting Dmitry Baryshkov (2022-02-01 07:10:55) 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 ff2218155b44..803fd6f25da1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -231,7 +216,7 @@ struct dpu_encoder_phys { atomic_t pending_ctlstart_cnt; atomic_t pending_kickoff_cnt; wait_queue_head_t pending_kickoff_wq; - struct dpu_encoder_irq irq[INTR_IDX_MAX]; + int irq[INTR_IDX_MAX]; }; static inline int dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys) @@ -729,20 +727,8 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init( phys_enc->split_role = p->split_role; phys_enc->intf_mode = INTF_MODE_VIDEO; phys_enc->enc_spinlock = p->enc_spinlock; - for (i = 0; i < INTR_IDX_MAX; i++) { - irq = _enc->irq[i]; - irq->irq_idx = -EINVAL; - } - - irq = _enc->irq[INTR_IDX_VSYNC]; - irq->name = "vsync_irq"; - irq->intr_idx = INTR_IDX_VSYNC; - irq->func = dpu_encoder_phys_vid_vblank_irq; - - irq = _enc->irq[INTR_IDX_UNDERRUN]; - irq->name = "underrun"; - irq->intr_idx = INTR_IDX_UNDERRUN; - irq->func = dpu_encoder_phys_vid_underrun_irq; + for (i = 0; i < INTR_IDX_MAX; i++) Can this use ARRAY_SIZE(phys_enc->irq)? Safer that way. Ack + phys_enc->irq[i] = -EINVAL; atomic_set(_enc->vblank_refcount, 0); atomic_set(_enc->pending_kickoff_cnt, 0); -- With best wishes Dmitry
Re: [PATCH v2 8/8] drm/msm/dpu: simplify intf allocation code
On 15/02/2022 20:51, Abhinav Kumar wrote: On 2/15/2022 6:16 AM, Dmitry Baryshkov wrote: Rather than passing DRM_MODE_ENCODER_* and letting dpu_encoder to guess, which intf type we mean, pass INTF_DSI/INTF_DP directly. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 26 +++-- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 4 ++-- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 5 ++-- 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index fa1dc088a672..597d40f78d38 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -490,7 +490,7 @@ void dpu_encoder_helper_split_config( hw_mdptop = phys_enc->hw_mdptop; disp_info = _enc->disp_info; - if (disp_info->intf_type != DRM_MODE_ENCODER_DSI) + if (disp_info->intf_type != INTF_DSI) return; /** @@ -552,7 +552,7 @@ static struct msm_display_topology dpu_encoder_get_topology( else topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1; - if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI) { + if (dpu_enc->disp_info.intf_type == INTF_DSI) { if (dpu_kms->catalog->dspp && (dpu_kms->catalog->dspp_count >= topology.num_lm)) topology.num_dspp = topology.num_lm; @@ -1074,7 +1074,7 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc) } - if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_TMDS && + if (dpu_enc->disp_info.intf_type == INTF_DP && dpu_enc->cur_master->hw_mdptop && dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select) dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select( @@ -1082,7 +1082,7 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc) _dpu_encoder_update_vsync_source(dpu_enc, _enc->disp_info); - if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI && + if (dpu_enc->disp_info.intf_type == INTF_DSI && !WARN_ON(dpu_enc->num_phys_encs == 0)) { unsigned bpc = dpu_enc->connector->display_info.bpc; for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { @@ -1949,7 +1949,6 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, { int ret = 0; int i = 0; - enum dpu_intf_type intf_type = INTF_NONE; struct dpu_enc_phys_init_params phys_params; if (!dpu_enc) { @@ -1965,15 +1964,6 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, phys_params.parent_ops = _encoder_parent_ops; phys_params.enc_spinlock = _enc->enc_spinlock; - switch (disp_info->intf_type) { - case DRM_MODE_ENCODER_DSI: - intf_type = INTF_DSI; - break; - case DRM_MODE_ENCODER_TMDS: - intf_type = INTF_DP; - break; - } - WARN_ON(disp_info->num_of_h_tiles < 1); DPU_DEBUG("dsi_info->num_of_h_tiles %d\n", disp_info->num_of_h_tiles); @@ -2005,11 +1995,11 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, i, controller_id, phys_params.split_role); phys_params.intf_idx = dpu_encoder_get_intf(dpu_kms->catalog, - intf_type, - controller_id); + disp_info->intf_type, + controller_id); if (phys_params.intf_idx == INTF_MAX) { DPU_ERROR_ENC(dpu_enc, "could not get intf: type %d, id %d\n", - intf_type, controller_id); + disp_info->intf_type, controller_id); ret = -EINVAL; } @@ -2092,7 +2082,7 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, timer_setup(_enc->frame_done_timer, dpu_encoder_frame_done_timeout, 0); - if (disp_info->intf_type == DRM_MODE_ENCODER_DSI) + if (disp_info->intf_type == INTF_DSI) timer_setup(_enc->vsync_event_timer, dpu_encoder_vsync_event_handler, 0); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index ebe3944355bb..3891bcbbe5a4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -36,7 +36,7 @@ void dpu_encoder_get_hw_resources(struct drm_encoder *encoder, /** * struct msm_display_info - defines display properties - * @intf_type: DRM_MODE_ENCODER_ type + * @intf_type: INTF_ type * @capabilities: Bitmask of display flags * @num_of_h_tiles: Number of horizontal tiles in case of split interface * @h_tile_instance: Controller instance used per tile. Number of elements is @@ -45,7 +45,7 @@ void dpu_encoder_get_hw_resources(struct drm_encoder *encoder, *
Re: [PATCH v6 01/10] mm: add zone device coherent type memory support
Jason Gunthorpe writes: > On Wed, Feb 16, 2022 at 09:31:03AM +0100, David Hildenbrand wrote: >> On 16.02.22 03:36, Alistair Popple wrote: >> > On Wednesday, 16 February 2022 1:03:57 PM AEDT Jason Gunthorpe wrote: >> >> On Wed, Feb 16, 2022 at 12:23:44PM +1100, Alistair Popple wrote: >> >> >> >>> Device private and device coherent pages are not marked with pte_devmap >> >>> and they >> >>> are backed by a struct page. The only way of inserting them is via >> >>> migrate_vma. >> >>> The refcount is decremented in zap_pte_range() on munmap() with special >> >>> handling >> >>> for device private pages. Looking at it again though I wonder if there >> >>> is any >> >>> special treatment required in zap_pte_range() for device coherent pages >> >>> given >> >>> they count as present pages. >> >> >> >> This is what I guessed, but we shouldn't be able to just drop >> >> pte_devmap on these pages without any other work?? Granted it does >> >> very little already.. >> > >> > Yes, I agree we need to check this more closely. For device private pages >> > not having pte_devmap is fine, because they are non-present swap entries so >> > they always get special handling in the swap entry paths but the same isn't >> > true for coherent device pages. >> >> I'm curious, how does the refcount of a PageAnon() DEVICE_COHERENT page >> look like when mapped? I'd assume it's also (currently) still offset by >> one, meaning, if it's mapped into a single page table it's always at >> least 2. > > Christoph fixed this offset by one and updated the DEVICE_COHERENT > patchset, I hope we will see that version merged. > >> >> I thought at least gup_fast needed to be touched or did this get >> >> handled by scanning the page list after the fact? >> > >> > Right, for gup I think the only special handling required is to prevent >> > pinning. I had assumed that check_and_migrate_movable_pages() would still >> > get >> > called for gup_fast but unless I've missed something I don't think it does. >> > That means gup_fast could still pin movable and coherent pages. Technically >> > that is ok for coherent pages, but it's undesirable. >> >> We really should have the same pinning rules for GUP vs. GUP-fast. >> is_pinnable_page() should be the right place for such checks (similarly >> as indicated in my reply to the migration series). > > Yes, I think this is a bug too. Agreed, I will add a fix for it to my series as I was surprised the rules for PUP-fast were different. I can see how this happened though - check_and_migrate_cma_pages() (the precursor to check_and_migrate_movable_pages()) was added before PUP-fast and FOLL_LONGTERM so I guess we just never added this check there. - Alistair > The other place that needs careful audit is all the callers using > vm_normal_page() - they must all be able to accept a ZONE_DEVICE page > if we don't set pte_devmap. > > Jason
Re: [PATCH] drm/msm/dpu: Disable boot loader configured data paths
On 15/02/2022 18:15, Bjorn Andersson wrote: On Tue 15 Feb 08:44 CST 2022, Dmitry Baryshkov wrote: On 15/02/2022 07:37, Bjorn Andersson wrote: It's typical for the bootloader to configure CTL_0 for the boot splash or EFIFB, but for non-DSI use cases the DPU driver tend to pick another CTL and the system might end up with two configured data paths producing data on the same INTF. In particular as the IOMMU configuration isn't retained from the bootloader one of the data paths will push underflow color, resulting in screen flickering. Naturally the end goal would be to inherit the bootloader's configuration and provide the user with a glitch-free handover from the boot configuration to a running DPU. But such effort will affect clocks, regulators, power-domains etc, and will take time to implement. So in the meantime this patch simply disables all the data paths, on platforms that has CTL_FETCH_ACTIVE, to avoid the graphical artifacts. Signed-off-by: Bjorn Andersson --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 13 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 6 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c| 2 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 17 + drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 8 5 files changed, 46 insertions(+) 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 02da9ecf71f1..69d4849484fa 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -357,6 +357,18 @@ static void dpu_hw_ctl_clear_all_blendstages(struct dpu_hw_ctl *ctx) DPU_REG_WRITE(c, CTL_FETCH_PIPE_ACTIVE, 0); } +static void dpu_hw_ctl_disable_boot_config(struct dpu_hw_ctl *ctx) +{ + if (ctx->caps->features & BIT(DPU_CTL_FETCH_ACTIVE)) { I see that you are changing only CTL_FETCH_PIPE_ACTIVE. However it still seems like a hack. You're not wrong, it certainly seems a little bit hacky. I think that it would be more appropriate to try to inherit the bootloader configuration. So the proposal here is, in my view, a stop-gap until we start to look at "continuous splash". What if instead we always disable boot config for all paths except CTL_0 (or CTL_0 and CTL_1)? On my laptop the bootloader sets up efifb using CTL_0. When Linux brings up the eDP interface it seems to skip DPU_CTL_SPLIT_DISPLAY ctls and picks CTL_2. As mentioned in the message, I now have both CTL_0 and CTL_2 pushing data to the one interface; resulting in flickering. Ah, I thought, it's the other way. Yep, the SPLIT_DISPLAY CTLs are precious, ideally they should be used only when required. + /* +* Disable the pipe fetch and trigger a start, to disable the +* data path +*/ + DPU_REG_WRITE(>hw, CTL_FETCH_PIPE_ACTIVE, 0); + DPU_REG_WRITE(>hw, CTL_START, 0x1); What about video vs cmd modes? Initially I was resetting a whole bunch of properties in the CTL, but all I want to do is stop the data flow. It's my expectation that the steps to follow will reset the interfaces and configure the actual data paths anew. Perhaps I'm missing some steps here, the documentation is not clear and this has the expected visual outcome... CTL_START is used only for WB and DSI command mode. Thus I'm surprised that you need it for the eDP (which should be using video mode). Regards, Bjorn + } +} + static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx, enum dpu_lm lm, struct dpu_hw_stage_cfg *stage_cfg) { @@ -590,6 +602,7 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops, ops->trigger_pending = dpu_hw_ctl_trigger_pending; ops->reset = dpu_hw_ctl_reset_control; ops->wait_reset_status = dpu_hw_ctl_wait_reset_status; + ops->disable_boot_config = dpu_hw_ctl_disable_boot_config; ops->clear_all_blendstages = dpu_hw_ctl_clear_all_blendstages; ops->setup_blendstage = dpu_hw_ctl_setup_blendstage; ops->get_bitmask_sspp = dpu_hw_ctl_get_bitmask_sspp; 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..c2734f6ab760 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h @@ -159,6 +159,12 @@ struct dpu_hw_ctl_ops { */ void (*clear_all_blendstages)(struct dpu_hw_ctl *ctx); + /** +* Disable the configuration setup by the bootloader +* @ctx : ctl path ctx pointer +*/ + void (*disable_boot_config)(struct dpu_hw_ctl *ctx); + /** * Configure layer mixer to pipe configuration * @ctx : ctl path ctx pointer diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index cedc631f8498..eef2f017031a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
Re: [PATCH v4 1/2] drm/msm/dpu: simplify clocks handling
On 16/02/2022 05:31, Stephen Boyd wrote: Quoting Dmitry Baryshkov (2022-01-31 13:05:12) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 60fe06018581..4d184122d63e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -405,10 +394,11 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc, trace_dpu_core_perf_update_clk(kms->dev, stop_req, clk_rate); - ret = _dpu_core_perf_set_core_clk_rate(kms, clk_rate); + if (clk_rate > kms->perf.max_core_clk_rate) + clk_rate = kms->perf.max_core_clk_rate; Using clk_rate = min(clk_rate, kms->perf.max_core_clk_rate) would be type safer. And min_t() would be explicit if the types don't match, but we should try to make them be compatible. Ack + ret = dev_pm_opp_set_rate(>pdev->dev, clk_rate); if (ret) { - DPU_ERROR("failed to set %s clock rate %llu\n", - kms->perf.core_clk->clk_name, clk_rate); + DPU_ERROR("failed to set core clock rate %llu\n", clk_rate); return ret; } @@ -529,13 +519,13 @@ void dpu_core_perf_destroy(struct dpu_core_perf *perf) int dpu_core_perf_init(struct dpu_core_perf *perf, struct drm_device *dev, struct dpu_mdss_cfg *catalog, - struct dss_clk *core_clk) + struct clk *core_clk) { perf->dev = dev; perf->catalog = catalog; perf->core_clk = core_clk; - perf->max_core_clk_rate = core_clk->max_rate; + perf->max_core_clk_rate = clk_get_rate(core_clk); if (!perf->max_core_clk_rate) { DPU_DEBUG("optional max core clk rate, use default\n"); perf->max_core_clk_rate = DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 2d385b4b7f5e..5f562413bb63 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -21,7 +21,6 @@ #include "dpu_hw_lm.h" #include "dpu_hw_interrupts.h" #include "dpu_hw_top.h" -#include "dpu_io_util.h" #include "dpu_rm.h" #include "dpu_core_perf.h" @@ -113,7 +112,8 @@ struct dpu_kms { struct platform_device *pdev; bool rpm_enabled; - struct dss_module_power mp; + struct clk_bulk_data *clocks; + int num_clocks; size_t? /* reference count bandwidth requests, so we know when we can * release bandwidth. Each atomic update increments, and frame- diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c index 131c1f1a869c..8c038416e119 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c @@ -29,7 +29,8 @@ struct dpu_irq_controller { struct dpu_mdss { struct msm_mdss base; void __iomem *mmio; - struct dss_module_power mp; + struct clk_bulk_data *clocks; + int num_clocks; size_t? struct dpu_irq_controller irq_controller; }; -- With best wishes Dmitry
Re: [PATCH v4 2/2] drm/msm/dp: rewrite dss_module_power to use bulk clock functions
On 16/02/2022 05:35, Stephen Boyd wrote: Quoting Dmitry Baryshkov (2022-01-31 13:05:13) diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index 094b39bfed8c..f16072f33cdb 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -10,7 +10,6 @@ #include #include -#include "dp_clk_util.h" #include "msm_drv.h" #define DP_LABEL "MDSS DP DISPLAY" @@ -106,6 +105,22 @@ struct dp_regulator_cfg { struct dp_reg_entry regs[DP_DEV_REGULATOR_MAX]; }; +enum dss_clk_type { + DSS_CLK_AHB, /* no set rate. rate controlled through rpm */ + DSS_CLK_PCLK, +}; + +struct dss_clk { + enum dss_clk_type type; + unsigned long rate; +}; + +struct dss_module_power { + unsigned int num_clk; + struct clk_bulk_data *clocks; + struct dss_clk *clk_config; +}; + /** * struct dp_parser - DP parser's data exposed to clients * diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c index b48b45e92bfa..318e1f8629cb 100644 --- a/drivers/gpu/drm/msm/dp/dp_power.c +++ b/drivers/gpu/drm/msm/dp/dp_power.c @@ -105,59 +105,40 @@ static int dp_power_clk_init(struct dp_power_private *power) ctrl = >parser->mp[DP_CTRL_PM]; stream = >parser->mp[DP_STREAM_PM]; - rc = msm_dss_get_clk(dev, core->clk_config, core->num_clk); + rc = devm_clk_bulk_get(dev, core->num_clk, core->clocks); Could we go further and devm_clk_bulk_get_all() and then either have some new clk API that goes through the bulk list and finds the one named something and hands over a pointer to it, think "clk_get() on top of clk_bulk_data", or just get the clk again that you want to set a rate on and have two pointers but otherwise it's a don't care. Then we wouldn't need to do much at all here to store the rate settable clk and find it in a loop. The clocks are stored in three different structures, because dp_power enables and disables them separately. See dp_power_clk_enable() and dp_ctrl.c. This devm_clk_bulk_get_all is out of question. On the other hand, we can call set_rate on disabled clocks. Let me see if we can get this into manageble state. if (rc) { DRM_ERROR("failed to get %s clk. err=%d\n", dp_parser_pm_name(DP_CORE_PM), rc); return rc; } - rc = msm_dss_get_clk(dev, ctrl->clk_config, ctrl->num_clk); + rc = devm_clk_bulk_get(dev, ctrl->num_clk, ctrl->clocks); if (rc) { DRM_ERROR("failed to get %s clk. err=%d\n", dp_parser_pm_name(DP_CTRL_PM), rc); - msm_dss_put_clk(core->clk_config, core->num_clk); return -ENODEV; } - rc = msm_dss_get_clk(dev, stream->clk_config, stream->num_clk); + rc = devm_clk_bulk_get(dev, stream->num_clk, stream->clocks); if (rc) { DRM_ERROR("failed to get %s clk. err=%d\n", dp_parser_pm_name(DP_CTRL_PM), rc); - msm_dss_put_clk(core->clk_config, core->num_clk); return -ENODEV; } return 0; } -static int dp_power_clk_deinit(struct dp_power_private *power) -{ - struct dss_module_power *core, *ctrl, *stream; - - core = >parser->mp[DP_CORE_PM]; - ctrl = >parser->mp[DP_CTRL_PM]; - stream = >parser->mp[DP_STREAM_PM]; - - if (!core || !ctrl || !stream) { - DRM_ERROR("invalid power_data\n"); - return -EINVAL; - } - - msm_dss_put_clk(ctrl->clk_config, ctrl->num_clk); - msm_dss_put_clk(core->clk_config, core->num_clk); - msm_dss_put_clk(stream->clk_config, stream->num_clk); - return 0; -} - static int dp_power_clk_set_link_rate(struct dp_power_private *power, - struct dss_clk *clk_arry, int num_clk, int enable) + struct dss_module_power *mp, int enable) { + struct dss_clk *clk_arry = mp->clk_config; + int num_clk = mp->num_clk; u32 rate; int i, rc = 0; for (i = 0; i < num_clk; i++) { - if (clk_arry[i].clk) { + if (mp->clocks[i].clk) { if (clk_arry[i].type == DSS_CLK_PCLK) { if (enable) rate = clk_arry[i].rate; @@ -168,9 +149,49 @@ static int dp_power_clk_set_link_rate(struct dp_power_private *power, if (rc) break; } + } else { + DRM_ERROR("%pS->%s: '%s' is not available\n", + __builtin_return_address(0), __func__, + mp->clocks[i].id); + rc = -EPERM; + break; + } + } + return rc; +} + +static int
Re: [PATCH v3 3/3] drm/msm/dp: replace DRM_DEBUG_DP marco with drm_dbg_dp
On 17/02/2022 03:22, Kuogee Hsieh wrote: On 2/16/2022 3:46 PM, Stephen Boyd wrote: Quoting Kuogee Hsieh (2022-02-02 10:56:39) Please add some commit text Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_audio.c | 49 +++-- drivers/gpu/drm/msm/dp/dp_catalog.c | 34 +++- drivers/gpu/drm/msm/dp/dp_ctrl.c | 106 +++- drivers/gpu/drm/msm/dp/dp_display.c | 68 +-- drivers/gpu/drm/msm/dp/dp_drm.c | 4 +- drivers/gpu/drm/msm/dp/dp_link.c | 99 +++-- drivers/gpu/drm/msm/dp/dp_panel.c | 43 +-- drivers/gpu/drm/msm/dp/dp_parser.c | 2 +- drivers/gpu/drm/msm/dp/dp_power.c | 20 --- 9 files changed, 246 insertions(+), 179 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c index d7e4a39..4fbbe0a 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -136,7 +136,8 @@ static void dp_audio_stream_sdp(struct dp_audio_private *audio) parity_byte = dp_audio_calculate_parity(new_value); value |= ((new_value << HEADER_BYTE_1_BIT) | (parity_byte << PARITY_BYTE_1_BIT)); - DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", + drm_dbg_dp((struct drm_device *)NULL, Why can't we pass the platform device pointer? Surely the cast is not necessary and in fact harmful. Platform device only available at top level (dp_display.c), other level has no access to platform device or drm_device. You can pass the platform device (or even better, drm device) to other driver blocks too. It's not something to be kept in secret in dp_display.c only. I will just apss NULL, such as drm_dbg_dp(NULL, ...), if not device available. -- With best wishes Dmitry
Re: [REPOST PATCH v4 02/13] drm/msm/dsi: Pass DSC params to drm_panel
On 2/10/2022 2:34 AM, 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 Also, fetch and pass DSC configuration for DSI panels to DPU encoder, which will enable and configure DSC hardware blocks accordingly. Signed-off-by: Dmitry Baryshkov Signed-off-by: Vinod Koul Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 2 ++ drivers/gpu/drm/msm/dsi/dsi.c | 5 + drivers/gpu/drm/msm/dsi/dsi.h | 1 + drivers/gpu/drm/msm/dsi/dsi_host.c | 22 ++ drivers/gpu/drm/msm/msm_drv.h | 8 include/drm/drm_panel.h | 7 +++ 6 files changed, 45 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 47fe11a84a77..ef6ddac22767 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -578,6 +578,8 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev, MSM_DISPLAY_CAP_CMD_MODE : MSM_DISPLAY_CAP_VID_MODE; + info.dsc = msm_dsi_get_dsc_config(priv->dsi[i]); + if (msm_dsi_is_bonded_dsi(priv->dsi[i]) && priv->dsi[other]) { rc = msm_dsi_modeset_init(priv->dsi[other], dev, encoder); if (rc) { diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 052548883d27..3aeac15e7421 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -20,6 +20,11 @@ bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi) return !(host_flags & MIPI_DSI_MODE_VIDEO); } +struct msm_display_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi) +{ + return msm_dsi_host_get_dsc_config(msm_dsi->host); +} + static int dsi_get_phy(struct msm_dsi *msm_dsi) { struct platform_device *pdev = msm_dsi->pdev; diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index c8dedc95428c..16cd9b2fce86 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -152,6 +152,7 @@ int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_bonded_dsi); int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi); void msm_dsi_host_snapshot(struct msm_disp_state *disp_state, struct mipi_dsi_host *host); void msm_dsi_host_test_pattern_en(struct mipi_dsi_host *host); +struct msm_display_dsc_config *msm_dsi_host_get_dsc_config(struct mipi_dsi_host *host); /* dsi phy */ struct msm_dsi_phy; diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 27553194f9fa..7e9913eff724 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -2059,9 +2059,24 @@ 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 drm_panel *panel; int ret; msm_host->dev = dev; + panel = msm_dsi_host_get_panel(_host->base); + + if (panel && panel->dsc) { + struct msm_display_dsc_config *dsc = msm_host->dsc; + + if (!dsc) { + dsc = devm_kzalloc(_host->pdev->dev, sizeof(*dsc), GFP_KERNEL); + if (!dsc) + return -ENOMEM; + dsc->drm = panel->dsc; + msm_host->dsc = dsc; + } + } + ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); if (ret) { pr_err("%s: alloc tx gem obj failed, %d\n", __func__, ret); @@ -2626,3 +2641,10 @@ void msm_dsi_host_test_pattern_en(struct mipi_dsi_host *host) dsi_write(msm_host, REG_DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER, DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER_SW_TRIGGER); } + +struct msm_display_dsc_config *msm_dsi_host_get_dsc_config(struct mipi_dsi_host *host) +{ + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + + return msm_host->dsc; +} diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 384f9bad4760..e7a312edfe67 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -119,6 +119,7 @@ struct msm_display_topology { * based on num_of_h_tiles * @is_te_using_watchdog_timer: Boolean to indicate watchdog TE is * used instead of panel TE in cmd mode panels + * @dsc: DSC configuration data for DSC-enabled displays */ struct msm_display_info { int intf_type; @@ -126,6 +127,7 @@ struct msm_display_info { uint32_t num_of_h_tiles; uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY]; bool
Re: [PATCH] drm/msm/dsi/phy: fix 7nm v4.0 settings for C-PHY mode
On 2/16/2022 4:08 PM, Dmitry Baryshkov wrote: The dsi_7nm_phy_enable() disagrees with downstream for glbl_str_swi_cal_sel_ctrl and glbl_hstx_str_ctrl_0 values. Update programmed settings to match downstream driver. To remove the possibility for such errors in future drop less_than_1500_mhz assignment and specify settings explicitly. Fixes: 5ac178381d26 ("drm/msm/dsi: support CPHY mode for 7nm pll/phy") Signed-off-by: Dmitry Baryshkov Yes, this matches what we have downstream Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 22 ++ 1 file changed, 14 insertions(+), 8 deletions(-) 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 36eb6109cb88..6e506feb111f 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -864,20 +864,26 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, /* Alter PHY configurations if data rate less than 1.5GHZ*/ less_than_1500_mhz = (clk_req->bitclk_rate <= 15); - /* For C-PHY, no low power settings for lower clk rate */ - if (phy->cphy_mode) - less_than_1500_mhz = false; - if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) { vreg_ctrl_0 = less_than_1500_mhz ? 0x53 : 0x52; - glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x00; - glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x39 : 0x3c; + if (phy->cphy_mode) { + glbl_rescode_top_ctrl = 0x00; + glbl_rescode_bot_ctrl = 0x3c; + } else { + glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x00; + glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x39 : 0x3c; + } glbl_str_swi_cal_sel_ctrl = 0x00; glbl_hstx_str_ctrl_0 = 0x88; } else { vreg_ctrl_0 = less_than_1500_mhz ? 0x5B : 0x59; - glbl_str_swi_cal_sel_ctrl = less_than_1500_mhz ? 0x03 : 0x00; - glbl_hstx_str_ctrl_0 = less_than_1500_mhz ? 0x66 : 0x88; + if (phy->cphy_mode) { + glbl_str_swi_cal_sel_ctrl = 0x03; + glbl_hstx_str_ctrl_0 = 0x66; + } else { + glbl_str_swi_cal_sel_ctrl = less_than_1500_mhz ? 0x03 : 0x00; + glbl_hstx_str_ctrl_0 = less_than_1500_mhz ? 0x66 : 0x88; + } glbl_rescode_top_ctrl = 0x03; glbl_rescode_bot_ctrl = 0x3c; }
[PATCH V2 12/12] drm: bridge: icn6211: Read and validate chip IDs before configuration
Read out the Vendor/Chip/Version ID registers from the chip before performing any configuration, and validate that the registers have correct values. This is mostly a simple test whether DSI register access does work, since that tends to be broken on various bridges. Signed-off-by: Marek Vasut Cc: Jagan Teki Cc: Maxime Ripard Cc: Robert Foss Cc: Sam Ravnborg Cc: Thomas Zimmermann To: dri-devel@lists.freedesktop.org --- V2: Rebase on next-20220214 --- drivers/gpu/drm/bridge/chipone-icn6211.c | 24 +++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index e0ca91e33774d..535dd65b3a4ed 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -153,6 +153,14 @@ static inline struct chipone *bridge_to_chipone(struct drm_bridge *bridge) return container_of(bridge, struct chipone, bridge); } +static void chipone_readb(struct chipone *icn, u8 reg, u8 *val) +{ + if (icn->interface_i2c) + *val = i2c_smbus_read_byte_data(icn->client, reg); + else + mipi_dsi_generic_read(icn->dsi, (u8[]){reg, 1}, 2, val, 1); +} + static void chipone_writeb(struct chipone *icn, u8 reg, u8 val) { if (icn->interface_i2c) @@ -251,7 +259,21 @@ static void chipone_atomic_enable(struct drm_bridge *bridge, const struct drm_bridge_state *bridge_state; u16 hfp, hbp, hsync; u32 bus_flags; - u8 pol; + u8 pol, id[4]; + + chipone_readb(icn, VENDOR_ID, id); + chipone_readb(icn, DEVICE_ID_H, id + 1); + chipone_readb(icn, DEVICE_ID_L, id + 2); + chipone_readb(icn, VERSION_ID, id + 3); + + dev_dbg(icn->dev, + "Chip IDs: Vendor=0x%02x Device=0x%02x:0x%02x Version=0x%02x\n", + id[0], id[1], id[2], id[3]); + + if (id[0] != 0xc1 || id[1] != 0x62 || id[2] != 0x11) { + dev_dbg(icn->dev, "Invalid Chip IDs, aborting configuration\n"); + return; + } /* Get the DPI flags from the bridge state. */ bridge_state = drm_atomic_get_new_bridge_state(state, bridge); -- 2.34.1
[PATCH V2 07/12] drm: bridge: icn6211: Disable DPI color swap
The chip is capable of swapping DPI RGB channels. The driver currently does not implement support for this functionality. Write the MIPI_PN_SWAP register to 0 to assure the color swap is disabled. Signed-off-by: Marek Vasut Cc: Jagan Teki Cc: Maxime Ripard Cc: Robert Foss Cc: Sam Ravnborg Cc: Thomas Zimmermann To: dri-devel@lists.freedesktop.org --- V2: Rebase on next-20220214 --- drivers/gpu/drm/bridge/chipone-icn6211.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index 2040596717139..f475426507f19 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -302,6 +302,7 @@ static void chipone_atomic_enable(struct drm_bridge *bridge, ICN6211_DSI(icn, MIPI_PD_CK_LANE, 0xa0); ICN6211_DSI(icn, PLL_CTRL(12), 0xff); + ICN6211_DSI(icn, MIPI_PN_SWAP, 0x00); /* DPI HS/VS/DE polarity */ pol = ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? BIST_POL_HSYNC_POL : 0) | -- 2.34.1
[PATCH V2 08/12] drm: bridge: icn6211: Set SYS_CTRL_1 to value used in examples
Both example code [1], [2] as well as one provided by custom panel vendor set register SYS_CTRL_1 to 0x88. What exactly does the value mean is unknown due to unavailable datasheet. Align this register value with example code. [1] https://github.com/rockchip-linux/kernel/blob/develop-4.19/drivers/gpu/drm/bridge/icn6211.c [2] https://github.com/tdjastrzebski/ICN6211-Configurator Signed-off-by: Marek Vasut Cc: Jagan Teki Cc: Maxime Ripard Cc: Robert Foss Cc: Sam Ravnborg Cc: Thomas Zimmermann To: dri-devel@lists.freedesktop.org --- V2: Rebase on next-20220214 --- drivers/gpu/drm/bridge/chipone-icn6211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index f475426507f19..07e698dc38cb4 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -314,7 +314,7 @@ static void chipone_atomic_enable(struct drm_bridge *bridge, chipone_configure_pll(icn, mode); ICN6211_DSI(icn, SYS_CTRL(0), 0x40); - ICN6211_DSI(icn, SYS_CTRL(1), 0x98); + ICN6211_DSI(icn, SYS_CTRL(1), 0x88); /* icn6211 specific sequence */ ICN6211_DSI(icn, MIPI_FORCE_0, 0x20); -- 2.34.1
[PATCH V2 10/12] drm: bridge: icn6211: Add I2C configuration support
The ICN6211 chip starts in I2C configuration mode after cold boot. Implement support for configuring the chip via I2C in addition to the current DSI LP command mode configuration support. The later seems to be available only on chips which have additional MCU on the panel/bridge board which preconfigures the ICN6211, while the I2C configuration mode added by this patch does not require any such MCU. Signed-off-by: Marek Vasut Cc: Jagan Teki Cc: Maxime Ripard Cc: Robert Foss Cc: Sam Ravnborg Cc: Thomas Zimmermann To: dri-devel@lists.freedesktop.org --- V2: - Drop the abridge variable - Rename chipone_dsi_setup to chipone_dsi_host_attach and call it from chipone_i2c_probe() --- drivers/gpu/drm/bridge/chipone-icn6211.c | 183 --- 1 file changed, 161 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index 71a08b11f9692..4a788fce06217 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -133,15 +134,18 @@ struct chipone { struct device *dev; + struct i2c_client *client; struct drm_bridge bridge; struct drm_display_mode mode; struct drm_bridge *panel_bridge; struct device_node *host_node; + struct mipi_dsi_device *dsi; struct gpio_desc *enable_gpio; struct regulator *vdd1; struct regulator *vdd2; struct regulator *vdd3; int dsi_lanes; + bool interface_i2c; }; static inline struct chipone *bridge_to_chipone(struct drm_bridge *bridge) @@ -152,9 +156,10 @@ static inline struct chipone *bridge_to_chipone(struct drm_bridge *bridge) static inline int chipone_dsi_write(struct chipone *icn, const void *seq, size_t len) { - struct mipi_dsi_device *dsi = to_mipi_dsi_device(icn->dev); - - return mipi_dsi_generic_write(dsi, seq, len); + if (icn->interface_i2c) + i2c_smbus_write_byte_data(icn->client, reg, val); + else + mipi_dsi_generic_write(icn->dsi, (u8[]){reg, val}, 2); } #define ICN6211_DSI(icn, seq...) \ @@ -259,7 +264,10 @@ static void chipone_atomic_enable(struct drm_bridge *bridge, bridge_state = drm_atomic_get_new_bridge_state(state, bridge); bus_flags = bridge_state->output_bus_cfg.flags; - ICN6211_DSI(icn, MIPI_CFG_PW, MIPI_CFG_PW_CONFIG_DSI); + if (icn->interface_i2c) + ICN6211_DSI(icn, MIPI_CFG_PW, MIPI_CFG_PW_CONFIG_I2C); + else + ICN6211_DSI(icn, MIPI_CFG_PW, MIPI_CFG_PW_CONFIG_DSI); ICN6211_DSI(icn, HACTIVE_LI, mode->hdisplay & 0xff); @@ -380,6 +388,57 @@ static void chipone_mode_set(struct drm_bridge *bridge, struct chipone *icn = bridge_to_chipone(bridge); drm_mode_copy(>mode, adjusted_mode); +}; + +static int chipone_dsi_attach(struct chipone *icn) +{ + struct mipi_dsi_device *dsi = icn->dsi; + int ret; + + dsi->lanes = icn->dsi_lanes; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET; + + ret = mipi_dsi_attach(dsi); + if (ret < 0) + dev_err(icn->dev, "failed to attach dsi\n"); + + return ret; +} + +static int chipone_dsi_host_attach(struct chipone *icn) +{ + struct device *dev = icn->dev; + struct mipi_dsi_device *dsi; + struct mipi_dsi_host *host; + int ret = 0; + + const struct mipi_dsi_device_info info = { + .type = "chipone", + .channel = 0, + .node = NULL, + }; + + host = of_find_mipi_dsi_host_by_node(icn->host_node); + if (!host) { + dev_err(dev, "failed to find dsi host\n"); + return -EPROBE_DEFER; + } + + dsi = mipi_dsi_device_register_full(host, ); + if (IS_ERR(dsi)) { + return dev_err_probe(dev, PTR_ERR(dsi), +"failed to create dsi device\n"); + } + + icn->dsi = dsi; + + ret = chipone_dsi_attach(icn); + if (ret < 0) + mipi_dsi_device_unregister(dsi); + + return ret; } static int chipone_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) @@ -488,9 +547,8 @@ static int chipone_parse_dt(struct chipone *icn) return 0; } -static int chipone_probe(struct mipi_dsi_device *dsi) +static int chipone_common_probe(struct device *dev, struct chipone **icnr) { - struct device *dev = >dev; struct chipone *icn; int ret; @@ -498,7 +556,6 @@ static int chipone_probe(struct mipi_dsi_device *dsi) if (!icn) return -ENOMEM; -
[PATCH V2 09/12] drm: bridge: icn6211: Implement atomic_get_input_bus_fmts
Implement .atomic_get_input_bus_fmts callback, which sets up the input (DSI-end) format, and that format can then be used in pipeline format negotiation between the DSI-end of this bridge and the other component closer to the scanout engine. Signed-off-by: Marek Vasut Cc: Jagan Teki Cc: Maxime Ripard Cc: Robert Foss Cc: Sam Ravnborg Cc: Thomas Zimmermann To: dri-devel@lists.freedesktop.org --- V2: Rebase on next-20220214 --- drivers/gpu/drm/bridge/chipone-icn6211.c | 27 1 file changed, 27 insertions(+) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index 07e698dc38cb4..71a08b11f9692 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -389,6 +389,32 @@ static int chipone_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flag return drm_bridge_attach(bridge->encoder, icn->panel_bridge, bridge, flags); } +#define MAX_INPUT_SEL_FORMATS 1 + +static u32 * +chipone_atomic_get_input_bus_fmts(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + u32 output_fmt, + unsigned int *num_input_fmts) +{ + u32 *input_fmts; + + *num_input_fmts = 0; + + input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts), +GFP_KERNEL); + if (!input_fmts) + return NULL; + + /* This is the DSI-end bus format */ + input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24; + *num_input_fmts = 1; + + return input_fmts; +} + static const struct drm_bridge_funcs chipone_bridge_funcs = { .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, @@ -398,6 +424,7 @@ static const struct drm_bridge_funcs chipone_bridge_funcs = { .atomic_post_disable= chipone_atomic_post_disable, .mode_set = chipone_mode_set, .attach = chipone_attach, + .atomic_get_input_bus_fmts = chipone_atomic_get_input_bus_fmts, }; static int chipone_parse_dt(struct chipone *icn) -- 2.34.1
[PATCH V2 05/12] drm: bridge: icn6211: Add generic DSI-to-DPI PLL configuration
The chip contains fractional PLL, however the driver currently hard-codes one specific PLL setting. Implement generic PLL parameter calculation code, so any DPI panel with arbitrary pixel clock can be attached to this bridge. The datasheet for this bridge is not available, the PLL behavior has been inferred from [1] and [2] and by analyzing the DPI pixel clock with scope. The PLL limits might be wrong, but at least the calculated values match all the example code available. This is better than one hard-coded pixel clock value anyway. [1] https://github.com/rockchip-linux/kernel/blob/develop-4.19/drivers/gpu/drm/bridge/icn6211.c [2] https://github.com/tdjastrzebski/ICN6211-Configurator Signed-off-by: Marek Vasut Cc: Jagan Teki Cc: Maxime Ripard Cc: Robert Foss Cc: Sam Ravnborg Cc: Thomas Zimmermann To: dri-devel@lists.freedesktop.org --- V2: Rebase on next-20220214 --- drivers/gpu/drm/bridge/chipone-icn6211.c | 87 +++- 1 file changed, 84 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index 7c013a08c7b00..7cc1f0d0dcdfd 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -163,6 +163,87 @@ static inline int chipone_dsi_write(struct chipone *icn, const void *seq, chipone_dsi_write(icn, d, ARRAY_SIZE(d)); \ } +static void chipone_configure_pll(struct chipone *icn, + const struct drm_display_mode *mode) +{ + unsigned int best_p = 0, best_m = 0, best_s = 0; + unsigned int delta, min_delta = 0x; + unsigned int freq_p, freq_s, freq_out; + unsigned int p_min, p_max; + unsigned int p, m, s; + unsigned int fin; + + /* +* DSI clock lane frequency (input into PLL) is calculated as: +* DSI_CLK = mode clock * bpp / dsi_data_lanes / 2 +* the 2 is there because the bus is DDR. +* +* DPI pixel clock frequency (output from PLL) is mode clock. +* +* The chip contains fractional PLL which works as follows: +* DPI_CLK = ((DSI_CLK / P) * M) / S +* P is pre-divider, register PLL_REF_DIV[3:0] is 2^(n+1) divider +* register PLL_REF_DIV[4] is extra 1:2 divider +* M is integer multiplier, register PLL_INT(0) is multiplier +* S is post-divider, register PLL_REF_DIV[7:5] is 2^(n+1) divider +* +* It seems the PLL input clock after applying P pre-divider have +* to be lower than 20 MHz. +*/ + fin = mode->clock * mipi_dsi_pixel_format_to_bpp(icn->dsi->format) / + icn->dsi_lanes / 2; /* in kHz */ + + /* Minimum value of P predivider for PLL input in 5..20 MHz */ + p_min = ffs(fin / 2); + p_max = (fls(fin / 5000) - 1) & 0x1f; + + for (p = p_min; p < p_max; p++) { /* PLL_REF_DIV[4,3:0] */ + freq_p = fin / BIT(p + 1); + if (freq_p == 0)/* Divider too high */ + break; + + for (s = 0; s < 0x7; s++) { /* PLL_REF_DIV[7:5] */ + freq_s = freq_p / BIT(s + 1); + if (freq_s == 0)/* Divider too high */ + break; + + m = mode->clock / freq_s; + + /* Multiplier is 8 bit */ + if (m > 0xff) + continue; + + /* Limit PLL VCO frequency to 1 GHz */ + freq_out = (fin * m) / BIT(p + 1); + if (freq_out > 100) + continue; + + /* Apply post-divider */ + freq_out /= BIT(s + 1); + + delta = abs(mode->clock - freq_out); + if (delta < min_delta) { + best_p = p; + best_m = m; + best_s = s; + min_delta = delta; + } + } + } + + dev_dbg(icn->dev, + "PLL: P[3:0]=2^%d P[4]=2*%d M=%d S[7:5]=2^%d delta=%d => DSI f_in=%d kHz ; DPI f_out=%ld kHz\n", + best_p, !!best_p, best_m, best_s + 1, min_delta, fin, + (fin * best_m) / BIT(best_p + best_s + 2)); + + /* Clock source selection fixed to MIPI DSI clock lane */ + ICN6211_DSI(icn, PLL_CTRL(6), PLL_CTRL_6_MIPI_CLK); + ICN6211_DSI(icn, PLL_REF_DIV, + (best_p ? PLL_REF_DIV_Pe : 0) | /* Prefer /2 pre-divider */ + PLL_REF_DIV_P(best_p) | PLL_REF_DIV_S(best_s)); + ICN6211_DSI(icn, PLL_INT(0), best_m); +} + static void chipone_atomic_enable(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state) { @@ -228,9
[PATCH V2 11/12] drm: bridge: icn6211: Rework ICN6211_DSI to chipone_writeb()
Rename and inline macro ICN6211_DSI() into function chipone_writeb() to keep all function names lower-case. No functional change. Signed-off-by: Marek Vasut Cc: Jagan Teki Cc: Maxime Ripard Cc: Robert Foss Cc: Sam Ravnborg Cc: Thomas Zimmermann To: dri-devel@lists.freedesktop.org --- V2: Rebase on next-20220214 --- drivers/gpu/drm/bridge/chipone-icn6211.c | 63 +++- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index 4a788fce06217..e0ca91e33774d 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -153,8 +153,7 @@ static inline struct chipone *bridge_to_chipone(struct drm_bridge *bridge) return container_of(bridge, struct chipone, bridge); } -static inline int chipone_dsi_write(struct chipone *icn, const void *seq, - size_t len) +static void chipone_writeb(struct chipone *icn, u8 reg, u8 val) { if (icn->interface_i2c) i2c_smbus_write_byte_data(icn->client, reg, val); @@ -162,12 +161,6 @@ static inline int chipone_dsi_write(struct chipone *icn, const void *seq, mipi_dsi_generic_write(icn->dsi, (u8[]){reg, val}, 2); } -#define ICN6211_DSI(icn, seq...) \ - { \ - const u8 d[] = { seq }; \ - chipone_dsi_write(icn, d, ARRAY_SIZE(d)); \ - } - static void chipone_configure_pll(struct chipone *icn, const struct drm_display_mode *mode) { @@ -242,11 +235,11 @@ static void chipone_configure_pll(struct chipone *icn, (fin * best_m) / BIT(best_p + best_s + 2)); /* Clock source selection fixed to MIPI DSI clock lane */ - ICN6211_DSI(icn, PLL_CTRL(6), PLL_CTRL_6_MIPI_CLK); - ICN6211_DSI(icn, PLL_REF_DIV, + chipone_writeb(icn, PLL_CTRL(6), PLL_CTRL_6_MIPI_CLK); + chipone_writeb(icn, PLL_REF_DIV, (best_p ? PLL_REF_DIV_Pe : 0) | /* Prefer /2 pre-divider */ PLL_REF_DIV_P(best_p) | PLL_REF_DIV_S(best_s)); - ICN6211_DSI(icn, PLL_INT(0), best_m); + chipone_writeb(icn, PLL_INT(0), best_m); } static void chipone_atomic_enable(struct drm_bridge *bridge, @@ -265,19 +258,19 @@ static void chipone_atomic_enable(struct drm_bridge *bridge, bus_flags = bridge_state->output_bus_cfg.flags; if (icn->interface_i2c) - ICN6211_DSI(icn, MIPI_CFG_PW, MIPI_CFG_PW_CONFIG_I2C); + chipone_writeb(icn, MIPI_CFG_PW, MIPI_CFG_PW_CONFIG_I2C); else - ICN6211_DSI(icn, MIPI_CFG_PW, MIPI_CFG_PW_CONFIG_DSI); + chipone_writeb(icn, MIPI_CFG_PW, MIPI_CFG_PW_CONFIG_DSI); - ICN6211_DSI(icn, HACTIVE_LI, mode->hdisplay & 0xff); + chipone_writeb(icn, HACTIVE_LI, mode->hdisplay & 0xff); - ICN6211_DSI(icn, VACTIVE_LI, mode->vdisplay & 0xff); + chipone_writeb(icn, VACTIVE_LI, mode->vdisplay & 0xff); /* * lsb nibble: 2nd nibble of hdisplay * msb nibble: 2nd nibble of vdisplay */ - ICN6211_DSI(icn, VACTIVE_HACTIVE_HI, + chipone_writeb(icn, VACTIVE_HACTIVE_HI, ((mode->hdisplay >> 8) & 0xf) | (((mode->vdisplay >> 8) & 0xf) << 4)); @@ -285,49 +278,49 @@ static void chipone_atomic_enable(struct drm_bridge *bridge, hsync = mode->hsync_end - mode->hsync_start; hbp = mode->htotal - mode->hsync_end; - ICN6211_DSI(icn, HFP_LI, hfp & 0xff); - ICN6211_DSI(icn, HSYNC_LI, hsync & 0xff); - ICN6211_DSI(icn, HBP_LI, hbp & 0xff); + chipone_writeb(icn, HFP_LI, hfp & 0xff); + chipone_writeb(icn, HSYNC_LI, hsync & 0xff); + chipone_writeb(icn, HBP_LI, hbp & 0xff); /* Top two bits of Horizontal Front porch/Sync/Back porch */ - ICN6211_DSI(icn, HFP_HSW_HBP_HI, + chipone_writeb(icn, HFP_HSW_HBP_HI, HFP_HSW_HBP_HI_HFP(hfp) | HFP_HSW_HBP_HI_HS(hsync) | HFP_HSW_HBP_HI_HBP(hbp)); - ICN6211_DSI(icn, VFP, mode->vsync_start - mode->vdisplay); + chipone_writeb(icn, VFP, mode->vsync_start - mode->vdisplay); - ICN6211_DSI(icn, VSYNC, mode->vsync_end - mode->vsync_start); + chipone_writeb(icn, VSYNC, mode->vsync_end - mode->vsync_start); - ICN6211_DSI(icn, VBP, mode->vtotal - mode->vsync_end); + chipone_writeb(icn, VBP, mode->vtotal - mode->vsync_end); /* dsi specific sequence */ - ICN6211_DSI(icn, SYNC_EVENT_DLY, 0x80); - ICN6211_DSI(icn, HFP_MIN, hfp & 0xff); + chipone_writeb(icn, SYNC_EVENT_DLY, 0x80); + chipone_writeb(icn, HFP_MIN, hfp & 0xff); /* DSI data lane count */ - ICN6211_DSI(icn, DSI_CTRL, +
[PATCH V2 03/12] drm: bridge: icn6211: Add HS/VS/DE polarity handling
The driver currently hard-codes HS/VS polarity to active-low and DE to active-high, which is not correct for a lot of supported DPI panels. Add the missing mode flag handling for HS/VS/DE polarity. Signed-off-by: Marek Vasut Cc: Jagan Teki Cc: Maxime Ripard Cc: Robert Foss Cc: Sam Ravnborg Cc: Thomas Zimmermann To: dri-devel@lists.freedesktop.org --- V2: Rebase on next-20220214 --- drivers/gpu/drm/bridge/chipone-icn6211.c | 16 +++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index e29e6a84c39a6..2ac8eb7e25f52 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -165,8 +165,16 @@ static void chipone_atomic_enable(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state) { struct chipone *icn = bridge_to_chipone(bridge); + struct drm_atomic_state *state = old_bridge_state->base.state; struct drm_display_mode *mode = >mode; + const struct drm_bridge_state *bridge_state; u16 hfp, hbp, hsync; + u32 bus_flags; + u8 pol; + + /* Get the DPI flags from the bridge state. */ + bridge_state = drm_atomic_get_new_bridge_state(state, bridge); + bus_flags = bridge_state->output_bus_cfg.flags; ICN6211_DSI(icn, MIPI_CFG_PW, MIPI_CFG_PW_CONFIG_DSI); @@ -206,7 +214,13 @@ static void chipone_atomic_enable(struct drm_bridge *bridge, ICN6211_DSI(icn, HFP_MIN, hfp & 0xff); ICN6211_DSI(icn, MIPI_PD_CK_LANE, 0xa0); ICN6211_DSI(icn, PLL_CTRL(12), 0xff); - ICN6211_DSI(icn, BIST_POL, BIST_POL_DE_POL); + + /* DPI HS/VS/DE polarity */ + pol = ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? BIST_POL_HSYNC_POL : 0) | + ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? BIST_POL_VSYNC_POL : 0) | + ((bus_flags & DRM_BUS_FLAG_DE_HIGH) ? BIST_POL_DE_POL : 0); + ICN6211_DSI(icn, BIST_POL, pol); + ICN6211_DSI(icn, PLL_CTRL(6), PLL_CTRL_6_MIPI_CLK); ICN6211_DSI(icn, PLL_REF_DIV, 0x71); ICN6211_DSI(icn, PLL_INT(0), 0x2b); -- 2.34.1
[PATCH V2 06/12] drm: bridge: icn6211: Use DSI burst mode without EoT and with LP command mode
The DSI burst mode is more energy efficient than the DSI sync pulse mode, make use of the burst mode since the chip supports it as well. Disable the generation of EoT packet, the chip ignores it, so no point in emitting it. Enable transmission of data in LP mode, otherwise register read via DSI does not work with this chip. Signed-off-by: Marek Vasut Cc: Jagan Teki Cc: Maxime Ripard Cc: Robert Foss Cc: Sam Ravnborg Cc: Thomas Zimmermann To: dri-devel@lists.freedesktop.org --- V2: Rebase on next-20220214 --- drivers/gpu/drm/bridge/chipone-icn6211.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index 7cc1f0d0dcdfd..2040596717139 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -485,7 +485,8 @@ static int chipone_probe(struct mipi_dsi_device *dsi) dsi->lanes = icn->dsi_lanes; dsi->format = MIPI_DSI_FMT_RGB888; - dsi->mode_flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET; ret = mipi_dsi_attach(dsi); if (ret < 0) { -- 2.34.1
[PATCH V2 01/12] drm: bridge: icn6211: Fix register layout
The chip register layout has nothing to do with MIPI DCS, the registers incorrectly marked as MIPI DCS in the driver are regular chip registers often with completely different function. Fill in the actual register names and bits from [1] and [2] and add the entire register layout, since the documentation for this chip is hard to come by. [1] https://github.com/rockchip-linux/kernel/blob/develop-4.19/drivers/gpu/drm/bridge/icn6211.c [2] https://github.com/tdjastrzebski/ICN6211-Configurator Fixes: ce517f18944e3 ("drm: bridge: Add Chipone ICN6211 MIPI-DSI to RGB bridge") Signed-off-by: Marek Vasut Cc: Jagan Teki Cc: Maxime Ripard Cc: Robert Foss Cc: Sam Ravnborg Cc: Thomas Zimmermann To: dri-devel@lists.freedesktop.org --- V2: Rebase on next-20220214 --- drivers/gpu/drm/bridge/chipone-icn6211.c | 134 --- 1 file changed, 117 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index e8f36dca56b33..4b8d1a5a50302 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -15,8 +15,19 @@ #include #include -#include - +#define VENDOR_ID 0x00 +#define DEVICE_ID_H0x01 +#define DEVICE_ID_L0x02 +#define VERSION_ID 0x03 +#define FIRMWARE_VERSION 0x08 +#define CONFIG_FINISH 0x09 +#define PD_CTRL(n) (0x0a + ((n) & 0x3)) /* 0..3 */ +#define RST_CTRL(n)(0x0e + ((n) & 0x1)) /* 0..1 */ +#define SYS_CTRL(n)(0x10 + ((n) & 0x7)) /* 0..4 */ +#define RGB_DRV(n) (0x18 + ((n) & 0x3)) /* 0..3 */ +#define RGB_DLY(n) (0x1c + ((n) & 0x1)) /* 0..1 */ +#define RGB_TEST_CTRL 0x1e +#define ATE_PLL_EN 0x1f #define HACTIVE_LI 0x20 #define VACTIVE_LI 0x21 #define VACTIVE_HACTIVE_HI 0x22 @@ -27,6 +38,95 @@ #define VFP0x27 #define VSYNC 0x28 #define VBP0x29 +#define BIST_POL 0x2a +#define BIST_POL_BIST_MODE(n) (((n) & 0xf) << 4) +#define BIST_POL_BIST_GEN BIT(3) +#define BIST_POL_HSYNC_POL BIT(2) +#define BIST_POL_VSYNC_POL BIT(1) +#define BIST_POL_DE_POLBIT(0) +#define BIST_RED 0x2b +#define BIST_GREEN 0x2c +#define BIST_BLUE 0x2d +#define BIST_CHESS_X 0x2e +#define BIST_CHESS_Y 0x2f +#define BIST_CHESS_XY_H0x30 +#define BIST_FRAME_TIME_L 0x31 +#define BIST_FRAME_TIME_H 0x32 +#define FIFO_MAX_ADDR_LOW 0x33 +#define SYNC_EVENT_DLY 0x34 +#define HSW_MIN0x35 +#define HFP_MIN0x36 +#define LOGIC_RST_NUM 0x37 +#define OSC_CTRL(n)(0x48 + ((n) & 0x7)) /* 0..5 */ +#define BG_CTRL0x4e +#define LDO_PLL0x4f +#define PLL_CTRL(n)(0x50 + ((n) & 0xf)) /* 0..15 */ +#define PLL_CTRL_6_EXTERNAL0x90 +#define PLL_CTRL_6_MIPI_CLK0x92 +#define PLL_CTRL_6_INTERNAL0x93 +#define PLL_REM(n) (0x60 + ((n) & 0x3)) /* 0..2 */ +#define PLL_DIV(n) (0x63 + ((n) & 0x3)) /* 0..2 */ +#define PLL_FRAC(n)(0x66 + ((n) & 0x3)) /* 0..2 */ +#define PLL_INT(n) (0x69 + ((n) & 0x1)) /* 0..1 */ +#define PLL_REF_DIV0x6b +#define PLL_REF_DIV_P(n) ((n) & 0xf) +#define PLL_REF_DIV_Pe BIT(4) +#define PLL_REF_DIV_S(n) (((n) & 0x7) << 5) +#define PLL_SSC_P(n) (0x6c + ((n) & 0x3)) /* 0..2 */ +#define PLL_SSC_STEP(n)(0x6f + ((n) & 0x3)) /* 0..2 */ +#define PLL_SSC_OFFSET(n) (0x72 + ((n) & 0x3)) /* 0..3 */ +#define GPIO_OEN 0x79 +#define MIPI_CFG_PW0x7a +#define MIPI_CFG_PW_CONFIG_DSI 0xc1 +#define MIPI_CFG_PW_CONFIG_I2C 0x3e +#define GPIO_SEL(n)(0x7b + ((n) & 0x1)) /* 0..1 */ +#define IRQ_SEL0x7d +#define DBG_SEL0x7e +#define DBG_SIGNAL 0x7f +#define MIPI_ERR_VECTOR_L 0x80 +#define MIPI_ERR_VECTOR_H 0x81 +#define MIPI_ERR_VECTOR_EN_L 0x82 +#define MIPI_ERR_VECTOR_EN_H 0x83 +#define MIPI_MAX_SIZE_L0x84 +#define MIPI_MAX_SIZE_H0x85 +#define DSI_CTRL 0x86 +#define DSI_CTRL_UNKNOWN 0x28 +#define DSI_CTRL_DSI_LANES(n) ((n) & 0x3) +#define MIPI_PN_SWAP 0x87 +#define MIPI_PN_SWAP_CLK BIT(4) +#define MIPI_PN_SWAP_D(n) BIT((n) & 0x3) +#define MIPI_SOT_SYNC_BIT_(n) (0x88 + ((n) & 0x1)) /* 0..1 */ +#define MIPI_ULPS_CTRL 0x8a +#define MIPI_CLK_CHK_VAR 0x8e +#define MIPI_CLK_CHK_INI 0x8f +#define MIPI_T_TERM_EN 0x90 +#define MIPI_T_HS_SETTLE 0x91 +#define MIPI_T_TA_SURE_PRE 0x92
[PATCH V2 04/12] drm: bridge: icn6211: Add DSI lane count DT property parsing
The driver currently hard-codes DSI lane count to two, however the chip is capable of operating in 1..4 DSI lanes mode. Parse 'data-lanes' DT property and program the result into DSI_CTRL register. Signed-off-by: Marek Vasut Cc: Jagan Teki Cc: Maxime Ripard Cc: Robert Foss Cc: Sam Ravnborg Cc: Thomas Zimmermann To: dri-devel@lists.freedesktop.org --- V2: Rebase on next-20220214 --- drivers/gpu/drm/bridge/chipone-icn6211.c | 21 - 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index 2ac8eb7e25f52..7c013a08c7b00 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -136,10 +136,12 @@ struct chipone { struct drm_bridge bridge; struct drm_display_mode mode; struct drm_bridge *panel_bridge; + struct device_node *host_node; struct gpio_desc *enable_gpio; struct regulator *vdd1; struct regulator *vdd2; struct regulator *vdd3; + int dsi_lanes; }; static inline struct chipone *bridge_to_chipone(struct drm_bridge *bridge) @@ -212,6 +214,11 @@ static void chipone_atomic_enable(struct drm_bridge *bridge, /* dsi specific sequence */ ICN6211_DSI(icn, SYNC_EVENT_DLY, 0x80); ICN6211_DSI(icn, HFP_MIN, hfp & 0xff); + + /* DSI data lane count */ + ICN6211_DSI(icn, DSI_CTRL, + DSI_CTRL_UNKNOWN | DSI_CTRL_DSI_LANES(icn->dsi_lanes - 1)); + ICN6211_DSI(icn, MIPI_PD_CK_LANE, 0xa0); ICN6211_DSI(icn, PLL_CTRL(12), 0xff); @@ -314,6 +321,7 @@ static const struct drm_bridge_funcs chipone_bridge_funcs = { static int chipone_parse_dt(struct chipone *icn) { struct device *dev = icn->dev; + struct device_node *endpoint; struct drm_panel *panel; int ret; @@ -350,6 +358,16 @@ static int chipone_parse_dt(struct chipone *icn) return PTR_ERR(icn->enable_gpio); } + endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, 0); + icn->dsi_lanes = of_property_count_u32_elems(endpoint, "data-lanes"); + icn->host_node = of_graph_get_remote_port_parent(endpoint); + of_node_put(endpoint); + + if (icn->dsi_lanes < 0 || icn->dsi_lanes > 4) + return -EINVAL; + if (!icn->host_node) + return -ENODEV; + ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, , NULL); if (ret) return ret; @@ -384,7 +402,7 @@ static int chipone_probe(struct mipi_dsi_device *dsi) drm_bridge_add(>bridge); - dsi->lanes = 4; + dsi->lanes = icn->dsi_lanes; dsi->format = MIPI_DSI_FMT_RGB888; dsi->mode_flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE; @@ -403,6 +421,7 @@ static int chipone_remove(struct mipi_dsi_device *dsi) mipi_dsi_detach(dsi); drm_bridge_remove(>bridge); + of_node_put(icn->host_node); return 0; } -- 2.34.1
[PATCH V2 02/12] drm: bridge: icn6211: Fix HFP_HSW_HBP_HI and HFP_MIN handling
The HFP_HSW_HBP_HI register must be programmed with 2 LSbits of each Horizontal Front Porch/Sync/Back Porch. Currently the driver programs this register to 0, which breaks displays with either value above 255. The HFP_MIN register must be set to the same value as HFP_LI, otherwise there is visible image distortion, usually in the form of missing lines at the bottom of the panel. Fix this by correctly programming the HFP_HSW_HBP_HI and HFP_MIN registers. Fixes: ce517f18944e3 ("drm: bridge: Add Chipone ICN6211 MIPI-DSI to RGB bridge") Signed-off-by: Marek Vasut Cc: Jagan Teki Cc: Maxime Ripard Cc: Robert Foss Cc: Sam Ravnborg Cc: Thomas Zimmermann To: dri-devel@lists.freedesktop.org --- V2: Rebase on next-20220214 --- drivers/gpu/drm/bridge/chipone-icn6211.c | 23 --- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index 4b8d1a5a50302..e29e6a84c39a6 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -35,6 +35,9 @@ #define HSYNC_LI 0x24 #define HBP_LI 0x25 #define HFP_HSW_HBP_HI 0x26 +#define HFP_HSW_HBP_HI_HFP(n) (((n) & 0x300) >> 4) +#define HFP_HSW_HBP_HI_HS(n) (((n) & 0x300) >> 6) +#define HFP_HSW_HBP_HI_HBP(n) (((n) & 0x300) >> 8) #define VFP0x27 #define VSYNC 0x28 #define VBP0x29 @@ -163,6 +166,7 @@ static void chipone_atomic_enable(struct drm_bridge *bridge, { struct chipone *icn = bridge_to_chipone(bridge); struct drm_display_mode *mode = >mode; + u16 hfp, hbp, hsync; ICN6211_DSI(icn, MIPI_CFG_PW, MIPI_CFG_PW_CONFIG_DSI); @@ -178,13 +182,18 @@ static void chipone_atomic_enable(struct drm_bridge *bridge, ((mode->hdisplay >> 8) & 0xf) | (((mode->vdisplay >> 8) & 0xf) << 4)); - ICN6211_DSI(icn, HFP_LI, mode->hsync_start - mode->hdisplay); + hfp = mode->hsync_start - mode->hdisplay; + hsync = mode->hsync_end - mode->hsync_start; + hbp = mode->htotal - mode->hsync_end; - ICN6211_DSI(icn, HSYNC_LI, mode->hsync_end - mode->hsync_start); - - ICN6211_DSI(icn, HBP_LI, mode->htotal - mode->hsync_end); - - ICN6211_DSI(icn, HFP_HSW_HBP_HI, 0x00); + ICN6211_DSI(icn, HFP_LI, hfp & 0xff); + ICN6211_DSI(icn, HSYNC_LI, hsync & 0xff); + ICN6211_DSI(icn, HBP_LI, hbp & 0xff); + /* Top two bits of Horizontal Front porch/Sync/Back porch */ + ICN6211_DSI(icn, HFP_HSW_HBP_HI, + HFP_HSW_HBP_HI_HFP(hfp) | + HFP_HSW_HBP_HI_HS(hsync) | + HFP_HSW_HBP_HI_HBP(hbp)); ICN6211_DSI(icn, VFP, mode->vsync_start - mode->vdisplay); @@ -194,7 +203,7 @@ static void chipone_atomic_enable(struct drm_bridge *bridge, /* dsi specific sequence */ ICN6211_DSI(icn, SYNC_EVENT_DLY, 0x80); - ICN6211_DSI(icn, HFP_MIN, 0x28); + ICN6211_DSI(icn, HFP_MIN, hfp & 0xff); ICN6211_DSI(icn, MIPI_PD_CK_LANE, 0xa0); ICN6211_DSI(icn, PLL_CTRL(12), 0xff); ICN6211_DSI(icn, BIST_POL, BIST_POL_DE_POL); -- 2.34.1
[PATCH V2 00/12] drm: bridge: icn6211: Fix hard-coded panel settings and add I2C support
This series fixes multiple problems with the ICN6211 driver and adds support for configuration of the chip via I2C bus. First, in the current state, the ICN6211 driver hard-codes DPI timing and clock settings specific to some unknown panel. The settings provided by panel driver are ignored. Using any other panel than the one for which this driver is currently hard-coded can lead to permanent damage of the panel (per display supplier warning, and it sure did in my case. The damage looks like multiple rows of dead pixels at the bottom of the panel, and this is not going away even after long power off time). Much of this series thus fixes incorrect register layout, DPI timing programming, clock generation by adding actual PLL configuration code. This series also adds lane count decoding instead of using hard-coded value, and fills in a couple of registers with likely correct default values. Second, this series adds support for I2C configuration of the ICN6211. The device can be configured either via DSI command mode or via I2C, the register layout is the same in both cases. Since the datasheet for this device is very hard to come by, a lot of information has been salvaged from [1] and [2]. [1] https://github.com/rockchip-linux/kernel/blob/develop-4.19/drivers/gpu/drm/bridge/icn6211.c [2] https://github.com/tdjastrzebski/ICN6211-Configurator Cc: Jagan Teki Cc: Maxime Ripard Cc: Robert Foss Cc: Sam Ravnborg Cc: Thomas Zimmermann To: dri-devel@lists.freedesktop.org Marek Vasut (12): drm: bridge: icn6211: Fix register layout drm: bridge: icn6211: Fix HFP_HSW_HBP_HI and HFP_MIN handling drm: bridge: icn6211: Add HS/VS/DE polarity handling drm: bridge: icn6211: Add DSI lane count DT property parsing drm: bridge: icn6211: Add generic DSI-to-DPI PLL configuration drm: bridge: icn6211: Use DSI burst mode without EoT and with LP command mode drm: bridge: icn6211: Disable DPI color swap drm: bridge: icn6211: Set SYS_CTRL_1 to value used in examples drm: bridge: icn6211: Implement atomic_get_input_bus_fmts drm: bridge: icn6211: Add I2C configuration support drm: bridge: icn6211: Rename ICN6211_DSI to chipone_writeb drm: bridge: icn6211: Read and validate chip IDs before configuration drivers/gpu/drm/bridge/chipone-icn6211.c | 510 --- 1 file changed, 458 insertions(+), 52 deletions(-) -- 2.34.1
Re: [PATCH v3 3/3] drm/msm/dp: replace DRM_DEBUG_DP marco with drm_dbg_dp
On 2/16/2022 3:46 PM, Stephen Boyd wrote: Quoting Kuogee Hsieh (2022-02-02 10:56:39) Please add some commit text Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_audio.c | 49 +++-- drivers/gpu/drm/msm/dp/dp_catalog.c | 34 +++- drivers/gpu/drm/msm/dp/dp_ctrl.c| 106 +++- drivers/gpu/drm/msm/dp/dp_display.c | 68 +-- drivers/gpu/drm/msm/dp/dp_drm.c | 4 +- drivers/gpu/drm/msm/dp/dp_link.c| 99 +++-- drivers/gpu/drm/msm/dp/dp_panel.c | 43 +-- drivers/gpu/drm/msm/dp/dp_parser.c | 2 +- drivers/gpu/drm/msm/dp/dp_power.c | 20 --- 9 files changed, 246 insertions(+), 179 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c index d7e4a39..4fbbe0a 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -136,7 +136,8 @@ static void dp_audio_stream_sdp(struct dp_audio_private *audio) parity_byte = dp_audio_calculate_parity(new_value); value |= ((new_value << HEADER_BYTE_1_BIT) | (parity_byte << PARITY_BYTE_1_BIT)); - DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", + drm_dbg_dp((struct drm_device *)NULL, Why can't we pass the platform device pointer? Surely the cast is not necessary and in fact harmful. Platform device only available at top level (dp_display.c), other level has no access to platform device or drm_device. I will just apss NULL, such as drm_dbg_dp(NULL, ...), if not device available.
[PATCH] drm/msm/dsi/phy: fix 7nm v4.0 settings for C-PHY mode
The dsi_7nm_phy_enable() disagrees with downstream for glbl_str_swi_cal_sel_ctrl and glbl_hstx_str_ctrl_0 values. Update programmed settings to match downstream driver. To remove the possibility for such errors in future drop less_than_1500_mhz assignment and specify settings explicitly. Fixes: 5ac178381d26 ("drm/msm/dsi: support CPHY mode for 7nm pll/phy") Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 22 ++ 1 file changed, 14 insertions(+), 8 deletions(-) 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 36eb6109cb88..6e506feb111f 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -864,20 +864,26 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, /* Alter PHY configurations if data rate less than 1.5GHZ*/ less_than_1500_mhz = (clk_req->bitclk_rate <= 15); - /* For C-PHY, no low power settings for lower clk rate */ - if (phy->cphy_mode) - less_than_1500_mhz = false; - if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) { vreg_ctrl_0 = less_than_1500_mhz ? 0x53 : 0x52; - glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x00; - glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x39 : 0x3c; + if (phy->cphy_mode) { + glbl_rescode_top_ctrl = 0x00; + glbl_rescode_bot_ctrl = 0x3c; + } else { + glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x00; + glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x39 : 0x3c; + } glbl_str_swi_cal_sel_ctrl = 0x00; glbl_hstx_str_ctrl_0 = 0x88; } else { vreg_ctrl_0 = less_than_1500_mhz ? 0x5B : 0x59; - glbl_str_swi_cal_sel_ctrl = less_than_1500_mhz ? 0x03 : 0x00; - glbl_hstx_str_ctrl_0 = less_than_1500_mhz ? 0x66 : 0x88; + if (phy->cphy_mode) { + glbl_str_swi_cal_sel_ctrl = 0x03; + glbl_hstx_str_ctrl_0 = 0x66; + } else { + glbl_str_swi_cal_sel_ctrl = less_than_1500_mhz ? 0x03 : 0x00; + glbl_hstx_str_ctrl_0 = less_than_1500_mhz ? 0x66 : 0x88; + } glbl_rescode_top_ctrl = 0x03; glbl_rescode_bot_ctrl = 0x3c; } -- 2.34.1
Re: [RFC PATCH 1/6] dt-bindings: display: imx: Add EPDC
On Mon, Feb 14, 2022 at 11:45:17PM +0100, Andreas Kemnade wrote: > Hi Rob, > > On Fri, 11 Feb 2022 09:46:27 -0600 > Rob Herring wrote: > > > On Sun, Feb 06, 2022 at 09:00:11AM +0100, Andreas Kemnade wrote: > > > Add a binding for the Electrophoretic Display Controller found at least > > > in the i.MX6. > > > > The first version was in i.MX50 (I helped design the register > > interface). Is that version compatible? > > > it has some differences, but that could be detected by EPDC_VERSION > register. I do not own such a device, so I cannot fully check. I have > not seen any driver with devicetree for IMX5. For now I am rejecting > anything which has a EPDC version which I cannot check. > > > > The timing subnode is directly here to avoid having display parameters > > > spread all over the plate. > > > > > > Supplies are organized the same way as in the fbdev driver in the > > > NXP/Freescale kernel forks. The regulators used for that purpose, > > > like the TPS65185, the SY7636A and MAX17135 have typically a single bit to > > > start a bunch of regulators of higher or negative voltage with a > > > well-defined timing. VCOM can be handled separately, but can also be > > > incorporated into that single bit. > > > > > > Signed-off-by: Andreas Kemnade > > > --- > > > .../bindings/display/imx/fsl,mxc-epdc.yaml| 159 ++ > > > 1 file changed, 159 insertions(+) > > > create mode 100644 > > > Documentation/devicetree/bindings/display/imx/fsl,mxc-epdc.yaml > > > > > > diff --git > > > a/Documentation/devicetree/bindings/display/imx/fsl,mxc-epdc.yaml > > > b/Documentation/devicetree/bindings/display/imx/fsl,mxc-epdc.yaml > > > new file mode 100644 > > > index ..7e0795cc3f70 > > > --- /dev/null > > > +++ b/Documentation/devicetree/bindings/display/imx/fsl,mxc-epdc.yaml > > > @@ -0,0 +1,159 @@ > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > > > +%YAML 1.2 > > > +--- > > > +$id: http://devicetree.org/schemas/display/imx/fsl,mxc-epdc.yaml# > > > +$schema: http://devicetree.org/meta-schemas/core.yaml# > > > + > > > +title: Freescale i.MX6 EPDC > > > + > > > +maintainers: > > > + - Andreas Kemnade > > > + > > > +description: | > > > + The EPDC is a controller for handling electronic paper displays found > > > in > > > + i.MX6 SoCs. > > > + > > > +properties: > > > + compatible: > > > +enum: > > > + - fsl,imx6sl-epdc > > > + - fsl,imx6sll-epdc > > > > Not compatible with each other? > > > differences are detectable by EPDC_VERSION register, so probably so > problem. NXP/Freescale kernel uses > fsl,imx6dl-epdc > and > fsl,imx7d-epdc (used also by imx6 devices with EPDC_VERSION = 3.0) > in their drivers. > > fsl,imx6dl-epdc > fsl,imx6sl-epdc > fsl,imx6sll-epdc > fsl,imx7d-epdc > in their dtsis. > > But the general rule is to use as less as possible compatible strings > if differences can be probed properly, so only one should be > sufficient? Which one? If you can probe all the differences, then just 'fsl,imx-epdc' is sufficient. Just document that so the next time around I don't forget and tell you it needs to be specific. Rob