Re: [PATCH 1/6] drm/ttm: move the LRU into resource handling v3

2022-02-16 Thread Christian König

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

2022-02-16 Thread Jani Nikula
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.

2022-02-16 Thread Hsin-Yi Wang
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

2022-02-16 Thread Dmitry Baryshkov

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

2022-02-16 Thread Dmitry Baryshkov

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

2022-02-16 Thread Dmitry Baryshkov

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

2022-02-16 Thread Lucas De Marchi

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'

2022-02-16 Thread Lucas De Marchi

+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

2022-02-16 Thread Dmitry Baryshkov

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

2022-02-16 Thread Abhinav Kumar




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'

2022-02-16 Thread kernel test robot
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

2022-02-16 Thread Matt Roper
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

2022-02-16 Thread Vinod Koul
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

2022-02-16 Thread Vinod Koul
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

2022-02-16 Thread Vinod Koul
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

2022-02-16 Thread Dmitry Baryshkov
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()

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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")

2022-02-16 Thread Dmitry Baryshkov
"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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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()

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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()

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Vinod Koul
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

2022-02-16 Thread Vinod Koul
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

2022-02-16 Thread Dmitry Baryshkov
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()

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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()

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov

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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Alex Deucher
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

2022-02-16 Thread Jim Cromie
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

2022-02-16 Thread Jim Cromie
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

2022-02-16 Thread Jim Cromie
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

2022-02-16 Thread Jim Cromie
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

2022-02-16 Thread Jim Cromie
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

2022-02-16 Thread Jim Cromie
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

2022-02-16 Thread Jim Cromie
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

2022-02-16 Thread Jim Cromie
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

2022-02-16 Thread Jim Cromie
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

2022-02-16 Thread Jim Cromie
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

2022-02-16 Thread Jim Cromie
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

2022-02-16 Thread Jim Cromie
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

2022-02-16 Thread Jim Cromie
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

2022-02-16 Thread Jim Cromie
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Abhinav Kumar




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

2022-02-16 Thread Abhinav Kumar




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

2022-02-16 Thread Abhinav Kumar




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

2022-02-16 Thread Abhinav Kumar




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

2022-02-16 Thread Abhinav Kumar




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

2022-02-16 Thread Abhinav Kumar




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

2022-02-16 Thread Hsin-Yi Wang
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

2022-02-16 Thread Xin Ji
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

2022-02-16 Thread Dmitry Baryshkov

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

2022-02-16 Thread Bjorn Andersson
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

2022-02-16 Thread Bjorn Andersson
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

2022-02-16 Thread Dmitry Baryshkov

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

2022-02-16 Thread Dmitry Baryshkov

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

2022-02-16 Thread Alistair Popple
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

2022-02-16 Thread Dmitry Baryshkov

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

2022-02-16 Thread Dmitry Baryshkov

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

2022-02-16 Thread Dmitry Baryshkov

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

2022-02-16 Thread Dmitry Baryshkov

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

2022-02-16 Thread Abhinav Kumar




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

2022-02-16 Thread Abhinav Kumar




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

2022-02-16 Thread Marek Vasut
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

2022-02-16 Thread Marek Vasut
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

2022-02-16 Thread Marek Vasut
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

2022-02-16 Thread Marek Vasut
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

2022-02-16 Thread Marek Vasut
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

2022-02-16 Thread Marek Vasut
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()

2022-02-16 Thread Marek Vasut
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

2022-02-16 Thread Marek Vasut
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

2022-02-16 Thread Marek Vasut
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

2022-02-16 Thread Marek Vasut
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

2022-02-16 Thread Marek Vasut
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

2022-02-16 Thread Marek Vasut
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

2022-02-16 Thread Marek Vasut
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

2022-02-16 Thread Kuogee Hsieh



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

2022-02-16 Thread Dmitry Baryshkov
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

2022-02-16 Thread Rob Herring
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


  1   2   3   >