RE: [PATCH v2 3/25] drm/amdgpu: Disable ABM when AC mode

2022-03-25 Thread Lin, Tsung-hua (Ryan)
[AMD Official Use Only]

Hi Christian,

There is already a string comparison in the same function. I just reference 
that to port this solution.



#define ACPI_AC_CLASS   "ac_adapter"


static int amdgpu_acpi_event(struct notifier_block *nb,
 unsigned long val,
 void *data)
{
struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, 
acpi_nb);
struct acpi_bus_event *entry = (struct acpi_bus_event *)data;

+   if (strcmp(entry->device_class, "battery") == 0) {
+   adev->pm.ac_power = power_supply_is_system_supplied() > 0;
+   }

if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) {  
<---here!
if (power_supply_is_system_supplied() > 0)
DRM_DEBUG_DRIVER("pm: AC\n");
else
DRM_DEBUG_DRIVER("pm: DC\n");

amdgpu_pm_acpi_event_handler(adev);
}

/* Check for pending SBIOS requests */
return amdgpu_atif_handler(adev, entry);
}

Thanks,
Ryan Lin.

-Original Message-
From: Koenig, Christian  
Sent: Friday, March 25, 2022 2:58 PM
To: Lin, Tsung-hua (Ryan) ; Wentland, Harry 
; Li, Sun peng (Leo) ; Deucher, 
Alexander ; david1.z...@amd.com; airl...@linux.ie; 
dan...@ffwll.ch; seanp...@chromium.org; b...@basnieuwenhuizen.nl; Kazlauskas, 
Nicholas ; sas...@kernel.org; 
markyac...@google.com; victorchengchi...@amd.com; 
ching-shih...@amd.corp-partner.google.com; Siqueira, Rodrigo 
; ddavenp...@chromium.org; 
amd-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; 
linux-ker...@vger.kernel.org; Li, Leon 
Subject: Re: [PATCH v2 3/25] drm/amdgpu: Disable ABM when AC mode

Am 25.03.22 um 05:05 schrieb Ryan Lin:
> Disable ABM feature when the system is running on AC mode to get the 
> more perfect contrast of the display.
>
> Signed-off-by: Ryan Lin 
>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c  |  4 ++
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c|  1 +
>   drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c | 58 ---
>   drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h   |  1 +
>   4 files changed, 42 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> index c560c1ab62ecb..bc8bb9aad2e36 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> @@ -822,6 +822,10 @@ static int amdgpu_acpi_event(struct notifier_block *nb,
>   struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, 
> acpi_nb);
>   struct acpi_bus_event *entry = (struct acpi_bus_event *)data;
>   
> + if (strcmp(entry->device_class, "battery") == 0) {

String comparison in a hot path is not something we usually like to see in the 
kernel.

Isn't there any other way to detect that? Like a flag or similar?

Regards,
Christian.

> + adev->pm.ac_power = power_supply_is_system_supplied() > 0;
> + }
> +
>   if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) {
>   if (power_supply_is_system_supplied() > 0)
>   DRM_DEBUG_DRIVER("pm: AC\n");
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index abfcc1304ba0c..3a0afe7602727 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -3454,6 +3454,7 @@ int amdgpu_device_init(struct amdgpu_device 
> *adev,
>   
>   adev->gfx.gfx_off_req_count = 1;
>   adev->pm.ac_power = power_supply_is_system_supplied() > 0;
> + adev->pm.old_ac_power = true;
>   
>   atomic_set(&adev->throttling_logging_enabled, 1);
>   /*
> diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c 
> b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
> index 54a1408c8015c..478a734b66926 100644
> --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
> +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
> @@ -23,6 +23,8 @@
>*
>*/
>   
> +#include 
> +#include "amdgpu.h"
>   #include "dmub_abm.h"
>   #include "dce_abm.h"
>   #include "dc.h"
> @@ -51,6 +53,7 @@
>   #define DISABLE_ABM_IMMEDIATELY 255
>   
>   
> +extern uint amdgpu_dm_abm_level;
>   
>   static void dmub_abm_enable_fractional_pwm(struct dc_context *dc)
>   {
> @@ -117,28 +120,6 @@ static void dmub_abm_init(struct abm *abm, uint32_t 
> backlight)
>   dmub_abm_enable_fractional_pwm(abm->ctx);
>   }
>   
> -static unsigned int dmub_abm_get_current_backlight(struct abm *abm) 
> -{
> - struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
> - unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL);
> -
> - /* return backlight in hardware format which is unsigned 17 bits, with
> -  * 1 bit integer and 16 bit fractional
> -  */
> - return backlight;
> -}
> -
> -static unsigned int dmub_abm_get_target_backlight(struct abm *abm) -{
> - struc

Re: [PATCH 1/2] drm/i915/ttm: limit where we apply TTM_PL_FLAG_CONTIGUOUS

2022-03-25 Thread Thomas Hellström



On 3/24/22 18:21, Matthew Auld wrote:

We only need this when allocating device local-memory, where this
influences the drm_buddy. Currently there is some funny behaviour where
an "in limbo" system memory object is lacking the relevant placement
flags etc. before we first allocate the ttm_tt, leading to ttm
performing a move when not needed, since the current placement is seen
as not compatible.

Suggested-by: Thomas Hellström 
Fixes: 2ed38cec5606 ("drm/i915: opportunistically apply ALLOC_CONTIGIOUS")
Signed-off-by: Matthew Auld 
Cc: Nirmoy Das 
---
  drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c 
b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index e4a06fcf741a..97e648fa76bd 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -133,6 +133,9 @@ i915_ttm_place_from_region(const struct intel_memory_region 
*mr,
memset(place, 0, sizeof(*place));
place->mem_type = intel_region_to_ttm_type(mr);
  
+	if (mr->type == INTEL_MEMORY_SYSTEM)

+   return;
+


Reviewed-by: Thomas Hellström 


if (flags & I915_BO_ALLOC_CONTIGUOUS)
place->flags |= TTM_PL_FLAG_CONTIGUOUS;
if (offset != I915_BO_INVALID_OFFSET) {


Re: [PATCH 2/2] drm/i915/migrate: move the sanity check

2022-03-25 Thread Thomas Hellström



On 3/24/22 18:21, Matthew Auld wrote:

Move the sanity check that both src and dst are never both system
memory, which should never happen on discrete, and likely means we have
a bug. The only exception is on integrated where we trigger this path in
the selftests.

Signed-off-by: Matthew Auld 
Cc: Thomas Hellström 
Cc: Nirmoy Das 
---
  drivers/gpu/drm/i915/gt/intel_migrate.c | 3 +--
  1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_migrate.c 
b/drivers/gpu/drm/i915/gt/intel_migrate.c
index 20444d6ceb3c..950fd6da146c 100644
--- a/drivers/gpu/drm/i915/gt/intel_migrate.c
+++ b/drivers/gpu/drm/i915/gt/intel_migrate.c
@@ -530,6 +530,7 @@ intel_context_migrate_copy(struct intel_context *ce,
int err;
  
  	GEM_BUG_ON(ce->vm != ce->engine->gt->migrate.context->vm);

+   GEM_BUG_ON(IS_DGFX(ce->engine->i915) && (!src_is_lmem && !dst_is_lmem));


Reviewed-by: Thomas Hellström 





*out = NULL;
  
  	GEM_BUG_ON(ce->ring->size < SZ_64K);

@@ -566,8 +567,6 @@ intel_context_migrate_copy(struct intel_context *ce,
src_offset = 0;
dst_offset = CHUNK_SZ;
if (HAS_64K_PAGES(ce->engine->i915)) {
-   GEM_BUG_ON(!src_is_lmem && !dst_is_lmem);
-
src_offset = 0;
dst_offset = 0;
if (src_is_lmem)


Re: [PATCH v2 3/25] drm/amdgpu: Disable ABM when AC mode

2022-03-25 Thread Christian König

Hi Ryan,

we should try to avoid that and if it isn't possible at least use some 
constant like ACPI_AC_CLASS.


Could be that the information isn't available otherwise. Alex should 
know more about that.


Regards,
Christian.

Am 25.03.22 um 08:09 schrieb Lin, Tsung-hua (Ryan):

[AMD Official Use Only]

Hi Christian,

There is already a string comparison in the same function. I just reference 
that to port this solution.



#define ACPI_AC_CLASS   "ac_adapter"


static int amdgpu_acpi_event(struct notifier_block *nb,
 unsigned long val,
 void *data)
{
struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, 
acpi_nb);
struct acpi_bus_event *entry = (struct acpi_bus_event *)data;

+   if (strcmp(entry->device_class, "battery") == 0) {
+   adev->pm.ac_power = power_supply_is_system_supplied() > 0;
+   }

if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) {  
<---here!
if (power_supply_is_system_supplied() > 0)
DRM_DEBUG_DRIVER("pm: AC\n");
else
DRM_DEBUG_DRIVER("pm: DC\n");

amdgpu_pm_acpi_event_handler(adev);
}

/* Check for pending SBIOS requests */
return amdgpu_atif_handler(adev, entry);
}

Thanks,
Ryan Lin.

-Original Message-
From: Koenig, Christian 
Sent: Friday, March 25, 2022 2:58 PM
To: Lin, Tsung-hua (Ryan) ; Wentland, Harry ; Li, Sun peng 
(Leo) ; Deucher, Alexander ; david1.z...@amd.com; 
airl...@linux.ie; dan...@ffwll.ch; seanp...@chromium.org; b...@basnieuwenhuizen.nl; Kazlauskas, Nicholas 
; sas...@kernel.org; markyac...@google.com; victorchengchi...@amd.com; 
ching-shih...@amd.corp-partner.google.com; Siqueira, Rodrigo ; ddavenp...@chromium.org; 
amd-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; linux-ker...@vger.kernel.org; Li, Leon 

Subject: Re: [PATCH v2 3/25] drm/amdgpu: Disable ABM when AC mode

Am 25.03.22 um 05:05 schrieb Ryan Lin:

Disable ABM feature when the system is running on AC mode to get the
more perfect contrast of the display.

Signed-off-by: Ryan Lin 

---
   drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c  |  4 ++
   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c|  1 +
   drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c | 58 ---
   drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h   |  1 +
   4 files changed, 42 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index c560c1ab62ecb..bc8bb9aad2e36 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -822,6 +822,10 @@ static int amdgpu_acpi_event(struct notifier_block *nb,
struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, 
acpi_nb);
struct acpi_bus_event *entry = (struct acpi_bus_event *)data;
   
+	if (strcmp(entry->device_class, "battery") == 0) {

String comparison in a hot path is not something we usually like to see in the 
kernel.

Isn't there any other way to detect that? Like a flag or similar?

Regards,
Christian.


+   adev->pm.ac_power = power_supply_is_system_supplied() > 0;
+   }
+
if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) {
if (power_supply_is_system_supplied() > 0)
DRM_DEBUG_DRIVER("pm: AC\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index abfcc1304ba0c..3a0afe7602727 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -3454,6 +3454,7 @@ int amdgpu_device_init(struct amdgpu_device
*adev,
   
   	adev->gfx.gfx_off_req_count = 1;

adev->pm.ac_power = power_supply_is_system_supplied() > 0;
+   adev->pm.old_ac_power = true;
   
   	atomic_set(&adev->throttling_logging_enabled, 1);

/*
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
index 54a1408c8015c..478a734b66926 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
@@ -23,6 +23,8 @@
*
*/
   
+#include 

+#include "amdgpu.h"
   #include "dmub_abm.h"
   #include "dce_abm.h"
   #include "dc.h"
@@ -51,6 +53,7 @@
   #define DISABLE_ABM_IMMEDIATELY 255
   
   
+extern uint amdgpu_dm_abm_level;
   
   static void dmub_abm_enable_fractional_pwm(struct dc_context *dc)

   {
@@ -117,28 +120,6 @@ static void dmub_abm_init(struct abm *abm, uint32_t 
backlight)
dmub_abm_enable_fractional_pwm(abm->ctx);
   }
   
-static unsigned int dmub_abm_get_current_backlight(struct abm *abm)

-{
-   struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
-   unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL);
-
-   /* return backlight in hardware format which is unsigned 17 bits, with
-   

Re: [PATCH 1/2] dma-buf: add dma_fence_unwrap

2022-03-25 Thread Christian König

Once more a ping on this here.

It's fixing a warning with sync_files and is already tested.

Regards,
Christian.

Am 21.03.22 um 11:31 schrieb Christian König:

[Adding Daniel]

Just once more a ping for this.

It's an important bug fix and the end user already reported that it 
works.


Regards,
Christian.

Am 14.03.22 um 12:14 schrieb Christian König:

Just a gentle ping.

This series is an important fix for drm-misc-next-fixes.

Regards,
Christian.

Am 11.03.22 um 12:02 schrieb Christian König:
Add a general purpose helper to deep dive into 
dma_fence_chain/dma_fence_array

structures and iterate over all the fences in them.

This is useful when we need to flatten out all fences in those 
structures.


Signed-off-by: Christian König 
---
  Documentation/driver-api/dma-buf.rst  |   6 +
  drivers/dma-buf/Makefile  |   1 +
  drivers/dma-buf/selftests.h   |   1 +
  drivers/dma-buf/st-dma-fence-unwrap.c | 279 
++

  include/linux/dma-fence-unwrap.h  |  99 +
  5 files changed, 386 insertions(+)
  create mode 100644 drivers/dma-buf/st-dma-fence-unwrap.c
  create mode 100644 include/linux/dma-fence-unwrap.h

diff --git a/Documentation/driver-api/dma-buf.rst 
b/Documentation/driver-api/dma-buf.rst

index 2cd7db82d9fe..7209500f08c8 100644
--- a/Documentation/driver-api/dma-buf.rst
+++ b/Documentation/driver-api/dma-buf.rst
@@ -194,6 +194,12 @@ DMA Fence Chain
  .. kernel-doc:: include/linux/dma-fence-chain.h
 :internal:
  +DMA Fence unwrap
+
+
+.. kernel-doc:: include/linux/dma-fence-unwrap.h
+   :internal:
+
  DMA Fence uABI/Sync File
  
  diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
index 511805dbeb75..4c9eb53ba3f8 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -12,6 +12,7 @@ dmabuf_selftests-y := \
  selftest.o \
  st-dma-fence.o \
  st-dma-fence-chain.o \
+    st-dma-fence-unwrap.o \
  st-dma-resv.o
    obj-$(CONFIG_DMABUF_SELFTESTS)    += dmabuf_selftests.o
diff --git a/drivers/dma-buf/selftests.h b/drivers/dma-buf/selftests.h
index 97d73aaa31da..851965867d9c 100644
--- a/drivers/dma-buf/selftests.h
+++ b/drivers/dma-buf/selftests.h
@@ -12,4 +12,5 @@
  selftest(sanitycheck, __sanitycheck__) /* keep first (igt 
selfcheck) */

  selftest(dma_fence, dma_fence)
  selftest(dma_fence_chain, dma_fence_chain)
+selftest(dma_fence_unwrap, dma_fence_unwrap)
  selftest(dma_resv, dma_resv)
diff --git a/drivers/dma-buf/st-dma-fence-unwrap.c 
b/drivers/dma-buf/st-dma-fence-unwrap.c

new file mode 100644
index ..d821faaebe93
--- /dev/null
+++ b/drivers/dma-buf/st-dma-fence-unwrap.c
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: MIT
+
+/*
+ * Copyright (C) 2022 Advanced Micro Devices, Inc.
+ */
+
+#include 
+#if 0
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#endif
+
+#include "selftest.h"
+
+#define CHAIN_SZ (4 << 10)
+
+static struct kmem_cache *slab_fences;
+
+static inline struct mock_fence {
+    struct dma_fence base;
+    spinlock_t lock;
+} *to_mock_fence(struct dma_fence *f) {
+    return container_of(f, struct mock_fence, base);
+}
+
+static const char *mock_name(struct dma_fence *f)
+{
+    return "mock";
+}
+
+static void mock_fence_release(struct dma_fence *f)
+{
+    kmem_cache_free(slab_fences, to_mock_fence(f));
+}
+
+static const struct dma_fence_ops mock_ops = {
+    .get_driver_name = mock_name,
+    .get_timeline_name = mock_name,
+    .release = mock_fence_release,
+};
+
+static struct dma_fence *mock_fence(void)
+{
+    struct mock_fence *f;
+
+    f = kmem_cache_alloc(slab_fences, GFP_KERNEL);
+    if (!f)
+    return NULL;
+
+    spin_lock_init(&f->lock);
+    dma_fence_init(&f->base, &mock_ops, &f->lock, 0, 0);
+
+    return &f->base;
+}
+
+static struct dma_fence *mock_array(unsigned int num_fences, ...)
+{
+    struct dma_fence_array *array;
+    struct dma_fence **fences;
+    va_list valist;
+    int i;
+
+    fences = kcalloc(num_fences, sizeof(*fences), GFP_KERNEL);
+    if (!fences)
+    return NULL;
+
+    va_start(valist, num_fences);
+    for (i = 0; i < num_fences; ++i)
+    fences[i] = va_arg(valist, typeof(*fences));
+    va_end(valist);
+
+    array = dma_fence_array_create(num_fences, fences,
+   dma_fence_context_alloc(1),
+   1, false);
+    if (!array)
+    goto cleanup;
+    return &array->base;
+
+cleanup:
+    for (i = 0; i < num_fences; ++i)
+    dma_fence_put(fences[i]);
+    kfree(fences);
+    return NULL;
+}
+
+static struct dma_fence *mock_chain(struct dma_fence *prev,
+    struct dma_fence *fence)
+{
+    struct dma_fence_chain *f;
+
+    f = dma_fence_chain_alloc();
+    if (!f) {
+    dma_fence_put(prev);
+    dma_fence_put(fence);
+    return NULL;
+    }
+
+    dma_fence_chain_init(f, prev, fence, 1);
+    return &f->base;
+}
+
+static int sanitycheck(void *arg)
+{
+    struct d

Re: [PATCH v2] drm/qxl: fix qxl can't use in arm64

2022-03-25 Thread Christian König

Am 24.03.22 um 11:49 schrieb Cong Liu:

qxl use ioremap to map ram_header and rom, in the arm64 implementation,
the device is mapped as DEVICE_nGnRE, it can not support unaligned
access. and qxl is a virtual device, it can be treated more like RAM
than actual MMIO registers. use ioremap_wc() replace it.

Signed-off-by: Cong Liu 


Looks sane to me, but I'm really not involved enough to fully judge.

Acked-by: Christian König 


---
  drivers/gpu/drm/qxl/qxl_kms.c | 4 ++--
  drivers/gpu/drm/qxl/qxl_ttm.c | 4 ++--
  2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c
index 4dc5ad13f12c..a054e4a00fe8 100644
--- a/drivers/gpu/drm/qxl/qxl_kms.c
+++ b/drivers/gpu/drm/qxl/qxl_kms.c
@@ -165,7 +165,7 @@ int qxl_device_init(struct qxl_device *qdev,
 (int)qdev->surfaceram_size / 1024,
 (sb == 4) ? "64bit" : "32bit");
  
-	qdev->rom = ioremap(qdev->rom_base, qdev->rom_size);

+   qdev->rom = ioremap_wc(qdev->rom_base, qdev->rom_size);
if (!qdev->rom) {
pr_err("Unable to ioremap ROM\n");
r = -ENOMEM;
@@ -183,7 +183,7 @@ int qxl_device_init(struct qxl_device *qdev,
goto rom_unmap;
}
  
-	qdev->ram_header = ioremap(qdev->vram_base +

+   qdev->ram_header = ioremap_wc(qdev->vram_base +
   qdev->rom->ram_header_offset,
   sizeof(*qdev->ram_header));
if (!qdev->ram_header) {
diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c
index b2e33d5ba5d0..95df5750f47f 100644
--- a/drivers/gpu/drm/qxl/qxl_ttm.c
+++ b/drivers/gpu/drm/qxl/qxl_ttm.c
@@ -82,13 +82,13 @@ int qxl_ttm_io_mem_reserve(struct ttm_device *bdev,
case TTM_PL_VRAM:
mem->bus.is_iomem = true;
mem->bus.offset = (mem->start << PAGE_SHIFT) + qdev->vram_base;
-   mem->bus.caching = ttm_cached;
+   mem->bus.caching = ttm_write_combined;
break;
case TTM_PL_PRIV:
mem->bus.is_iomem = true;
mem->bus.offset = (mem->start << PAGE_SHIFT) +
qdev->surfaceram_base;
-   mem->bus.caching = ttm_cached;
+   mem->bus.caching = ttm_write_combined;
break;
default:
return -EINVAL;




Re: [PATCH] drm/amd: Re-classify some log messages in commit path

2022-03-25 Thread Christian König

Am 25.03.22 um 01:06 schrieb Sean Paul:

From: Sean Paul 

ATOMIC and DRIVER log categories do not typically contain per-frame log
messages. This patch re-classifies some messages in amd to chattier
categories to keep ATOMIC/DRIVER quiet.

Signed-off-by: Sean Paul 


Please use drm/amdgpu for the subject line in the future, apart from 
that looks like a really clean patch to me.


Feel free to add an Acked-by: Christian König 


---
  drivers/gpu/drm/amd/amdgpu/amdgpu_display.c   | 5 +++--
  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 
  2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index fae5c1debfad..1fcbab2fd3c3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -113,8 +113,9 @@ static void amdgpu_display_flip_work_func(struct 
work_struct *__work)
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
  
  
-	DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_SUBMITTED, work: %p,\n",

-amdgpu_crtc->crtc_id, amdgpu_crtc, 
work);
+   drm_dbg_vbl(adev_to_drm(adev),
+   "crtc:%d[%p], pflip_stat:AMDGPU_FLIP_SUBMITTED, work: 
%p,\n",
+   amdgpu_crtc->crtc_id, amdgpu_crtc, work);
  
  }
  
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

index b30656959fd8..45d130f86114 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -9248,7 +9248,7 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
&bundle->flip_addrs[planes_count].address,
afb->tmz_surface, false);
  
-		DRM_DEBUG_ATOMIC("plane: id=%d dcc_en=%d\n",

+   drm_dbg_state(state->dev, "plane: id=%d dcc_en=%d\n",
 new_plane_state->plane->index,
 bundle->plane_infos[planes_count].dcc.enable);
  
@@ -9282,7 +9282,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,

dc_plane,

bundle->flip_addrs[planes_count].flip_timestamp_in_us);
  
-		DRM_DEBUG_ATOMIC("%s Flipping to hi: 0x%x, low: 0x%x\n",

+   drm_dbg_state(state->dev, "%s Flipping to hi: 0x%x, low: 
0x%x\n",
 __func__,
 
bundle->flip_addrs[planes_count].address.grph.addr.high_part,
 
bundle->flip_addrs[planes_count].address.grph.addr.low_part);
@@ -9624,7 +9624,7 @@ static void amdgpu_dm_atomic_commit_tail(struct 
drm_atomic_state *state)
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
  
-		DRM_DEBUG_ATOMIC(

+   drm_dbg_state(state->dev,
"amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, 
"
"planes_changed:%d, mode_changed:%d,active_changed:%d,"
"connectors_changed:%d\n",
@@ -10328,7 +10328,7 @@ static int dm_update_crtc_state(struct 
amdgpu_display_manager *dm,
if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
goto skip_modeset;
  
-	DRM_DEBUG_ATOMIC(

+   drm_dbg_state(state->dev,
"amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
"planes_changed:%d, mode_changed:%d,active_changed:%d,"
"connectors_changed:%d\n",




Re: [RFC] drm/i915: Split out intel_vtd_active and run_as_guest to own header

2022-03-25 Thread Tvrtko Ursulin



On 24/03/2022 18:57, Jani Nikula wrote:

On Thu, 24 Mar 2022, Tvrtko Ursulin  wrote:

On 24/03/2022 11:57, Jani Nikula wrote:

On Thu, 24 Mar 2022, Tvrtko Ursulin  wrote:

On 24/03/2022 09:31, Jani Nikula wrote:

On Tue, 22 Mar 2022, Tvrtko Ursulin  wrote:

From: Tvrtko Ursulin 

...

Signed-off-by: Tvrtko Ursulin 
Cc: Jani Nikula 
Cc: Lucas De Marchi 
---
Typed up how I see it - bash away.


So is intel_vtd_active() so performance critical that it needs to be
inline?

We're passing struct drm_i915_private * everywhere we can, and it just
feels silly to use struct drm_device * to avoid the include.

Static inlines considered harmful. :p


Same as it is ;), and gee, who was it that he said he was just trying to
declutter i915_drv.h.. ;p


Not at the cost of clarity elsewhere!


To be clear now you oppose intel_vtd_active taking struct device? I
thought you expressed general agreement when I presented the idea in the
previous thread.

I don't mind hugely to go either way, but I also don't see how taking
struct device makes anything unclear. (I only think
intel_vtd_run_as_guest is really wrong in this story but that's old news.)

And if I make it take i915 then I would want to name it i915_vtd_active
as well. But then you wouldn't like that.

Should we just stuff all this into i915_utils for now, as I think Lucas
suggested? Static inline or not, I don't care.


Just general grumpiness.

Acked-by: Jani Nikula 


No worries. Ack is for this version or with i915_ prefixes in 
i915_utils.h/c?


Regards,

Tvrtko


[PATCH v2] drm/qxl: fix qxl can't use in arm64

2022-03-25 Thread Cong Liu
qxl use ioremap to map ram_header and rom, in the arm64 implementation,
the device is mapped as DEVICE_nGnRE, it can not support unaligned
access. and qxl is a virtual device, it can be treated more like RAM
than actual MMIO registers. use ioremap_wc() replace it.

Signed-off-by: Cong Liu 
---
 drivers/gpu/drm/qxl/qxl_kms.c | 4 ++--
 drivers/gpu/drm/qxl/qxl_ttm.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c
index 4dc5ad13f12c..a054e4a00fe8 100644
--- a/drivers/gpu/drm/qxl/qxl_kms.c
+++ b/drivers/gpu/drm/qxl/qxl_kms.c
@@ -165,7 +165,7 @@ int qxl_device_init(struct qxl_device *qdev,
 (int)qdev->surfaceram_size / 1024,
 (sb == 4) ? "64bit" : "32bit");
 
-   qdev->rom = ioremap(qdev->rom_base, qdev->rom_size);
+   qdev->rom = ioremap_wc(qdev->rom_base, qdev->rom_size);
if (!qdev->rom) {
pr_err("Unable to ioremap ROM\n");
r = -ENOMEM;
@@ -183,7 +183,7 @@ int qxl_device_init(struct qxl_device *qdev,
goto rom_unmap;
}
 
-   qdev->ram_header = ioremap(qdev->vram_base +
+   qdev->ram_header = ioremap_wc(qdev->vram_base +
   qdev->rom->ram_header_offset,
   sizeof(*qdev->ram_header));
if (!qdev->ram_header) {
diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c
index b2e33d5ba5d0..95df5750f47f 100644
--- a/drivers/gpu/drm/qxl/qxl_ttm.c
+++ b/drivers/gpu/drm/qxl/qxl_ttm.c
@@ -82,13 +82,13 @@ int qxl_ttm_io_mem_reserve(struct ttm_device *bdev,
case TTM_PL_VRAM:
mem->bus.is_iomem = true;
mem->bus.offset = (mem->start << PAGE_SHIFT) + qdev->vram_base;
-   mem->bus.caching = ttm_cached;
+   mem->bus.caching = ttm_write_combined;
break;
case TTM_PL_PRIV:
mem->bus.is_iomem = true;
mem->bus.offset = (mem->start << PAGE_SHIFT) +
qdev->surfaceram_base;
-   mem->bus.caching = ttm_cached;
+   mem->bus.caching = ttm_write_combined;
break;
default:
return -EINVAL;
-- 
2.25.1



[PATCH] drm/amd/display: Fix pointer dereferenced before checking

2022-03-25 Thread Haowen Bai
The value actual_pix_clk_100Hz is dereferencing pointer pix_clk_params
before pix_clk_params is being null checked. Fix this by assigning
pix_clk_params->requested_pix_clk_100hz to actual_pix_clk_100Hz only if
pix_clk_params is not NULL, otherwise just NULL.

Signed-off-by: Haowen Bai 
---
 drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c 
b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
index 2c7eb98..4db45bb 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -1162,7 +1162,7 @@ static uint32_t dcn3_get_pix_clk_dividers(
struct pixel_clk_params *pix_clk_params,
struct pll_settings *pll_settings)
 {
-   unsigned long long actual_pix_clk_100Hz = 
pix_clk_params->requested_pix_clk_100hz;
+   unsigned long long actual_pix_clk_100Hz = pix_clk_params ? 
pix_clk_params->requested_pix_clk_100hz : 0;
struct dce110_clk_src *clk_src;
 
clk_src = TO_DCE110_CLK_SRC(cs);
-- 
2.7.4



[PATCH] drm/amd/display: Fix pointer dereferenced before checking

2022-03-25 Thread Haowen Bai
The pointer edid_buf is dereferencing pointer edid before edid is being
 null checked. Fix this by assigning edid->raw_edid to edid_buf only if 
edid is not NULL, otherwise just NULL.

Signed-off-by: Haowen Bai 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 29f07c2..360401d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -89,7 +89,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
 {
struct amdgpu_dm_connector *aconnector = link->priv;
struct drm_connector *connector = &aconnector->base;
-   struct edid *edid_buf = (struct edid *) edid->raw_edid;
+   struct edid *edid_buf = edid ? (struct edid *) edid->raw_edid : NULL;
struct cea_sad *sads;
int sad_count = -1;
int sadb_count = -1;
-- 
2.7.4



回复: Re: 回复: Re: 回复: Re: [PATCH v1 1/2] drm/qxl: replace ioremap by ioremap_cache on arm64

2022-03-25 Thread liucong2
Hi Christian,Can you help explain more detail under what circumstances userspace mappingwill be problematic, you mean cached mappings also need adjustment infunction ttm_prot_from_caching?Regards,Cong.
        主 题:Re: 回复: Re: 回复: Re: [PATCH v1 1/2] drm/qxl: replace ioremap by ioremap_cache on arm64
            日 期:2022-03-23 18:17
            发件人:Christian König
            收件人:liucong2@kylinos.cnairlied@redhat.comkraxel@redhat.comairlied@linux.iedaniel@ffwll.chray.huang@amd.comvirtualization@lists.linux-foundation.orgspice-devel@lists.freedesktop.orgdri-de...@lists.freedesktop.org
            
        
        Hi Cong,
    
    yes I've seen that, but that is still not sufficient.
    
    You need to update the check in ttm_module.c as well or otherwise
    your userspace mapping might not work correctly either.
    
    Regards,
    Christian. 
    
    Am 23.03.22 um 11:00 schrieb      liuco...@kylinos.cn:
       
      Hi Christian,
      another commit fix the case in ttm. I send two patches at the
        same time, but seems I miss '--cover-letter' when run format-patch or some other bad
        operation.
        Regards,Cong.
        
        
               主 题:Re: 回复: Re: [PATCH v1 1/2] drm/qxl: replace
            ioremap by ioremap_cache on arm64            
          日 期:2022-03-23 17:34            
          发件人:Christian König            
          收件人:liucong2@kylinos.cnairlied@redhat.comkraxel@redhat.comairlied@linux.iedaniel@ffwll.chray.huang@amd.comvirtualization@lists.linux-foundation.orgspice-devel@lists.freedesktop.orgdri-de...@lists.freedesktop.org
                             
               Hi Cong,
                 
                 well than Dave must decide what to do here.
                 
                 When QXL emulates a device it should also not use
              memory accesses    which won't work on a physical device.
                 
                 BTW: Your patch is really buggy, it misses the cases in
              ttm_module.c
                 
                 Regards,
                 Christian.
                 
                 Am 23.03.22 um 09:48 schrieb
                     liuco...@kylinos.cn:
                   Hi Christian,
                       according to 'Arm Architecture Reference Manual
                  Armv8,for        Armv8-Aarchitecture profile' pdf E2.6.5
                       E2.6.5 Generation of Alignment faults by load/store
                  multiple        accesses to Device memory
                       	When
                  FEAT_LSMAOC is        implemented and the value of the
                  applicable nTLSMD	field is 0, any
                  memory        access by an AArch32 Load Multiple or
                  Store 	Multiple
                  instruction to        an address that the stage 1
                  translation 	assigns as
                  Device-nGRE,        Device-nGnRE, or Device-nGnRnE
                  generates 	an Alignment
                  fault.
                     so it seems not just some ARM boards doesn't allow
                  unaligned        access to MMIO space, all pci memory mapped as Device-nGnRE in arm64
                  cannot        supportunaligned access. and qxl is a device simulated by
                  qemu, it        should be able to access to MMIO space in a more flexible way(PROT_NORMAL)
                  than the real        physical graphics card.
                       
                       
                       Cong.
                       
                       
                         
                         
                                主 题:Re: [PATCH v1
                    1/2]          drm/qxl: replace ioremap by
                    ioremap_cache on arm64                   
                         日 期:2022-03-23
                    15:15                   
                         发件人:Christian
                    König                   
                         收件人:CongLiuairlied@redhat.comkraxel@redhat.comairlied@linux.iedaniel@ffwll.chray.huang@amd.comvirtualization@lists.linux-foundation.orgspice-devel@lists.freedesktop.orgdri-de...@lists.freedesktop.org
                                            
                                Am 22.03.22 um 10:34 schrieb Cong Liu:
                         > qxl use ioremap to map ram_header and rom,
                  in the arm64        implementation,
                         > the device is mapped as DEVICE_nGnRE, it
                  can not support        unaligned
                         > access.
                         
                         Well that some ARM boards doesn't allow
                  unaligned access to MMIO        space 
                         is a well known bug of those ARM boards.
                         
                         So as far as I know this is a hardware bug you
                  are trying to        workaround 
                         here and I'm not 100% 

回复: Re: 回复: Re: 回复: Re: 回复: Re: [PATCH v1 1/2] drm/qxl: replace ioremap by ioremap_cache on arm64

2022-03-25 Thread liucong2
ok, thanks, a lot of our customer use qxl on x86 before, so it still needto supoort qxl on arm64.

    Regards,Cong.
        主 题:Re: 回复: Re: 回复: Re: 回复: Re: [PATCH v1 1/2] drm/qxl: replace ioremap by ioremap_cache on arm64
            日 期:2022-03-24 18:26
            发件人:Gerd Hoffmann
            收件人:Christian König
            
        
        On Thu, Mar 24, 2022 at 10:20:40AM +0100, Christian König wrote:> Hi Cong,> > when I understand Robin correctly all mapping (host, guest, kernel,> userspace etc..) must have the same caching attributes unless you use the> S2FWB feature introduced with Armv8.4.> > If you don't follow those rules you usually run into coherency issues or> even worse system hangs. So you not only need to adjust the kernel mappings,> but also the function for userspace mappings to follow those rules.That matches my understanding.For qxl specifically: when using the xork qxl driver getting theuserspace mappings right is essential because userspace will write qxlcommand buffers then.  When using the xorg modesetting driver or waylandthe worst thing happening would be display corruption because userspacewill only map dumb bo's for pixel data.I'm wondering though why you are keen on getting qxl work instead ofjust using virtio-gpu?take care,  Gerd

回复: Re: [PATCH v1 1/2] drm/qxl: replace ioremap by ioremap_cache on arm64

2022-03-25 Thread liucong2
Hi,I didn't understand the mapping attribute mismatch issue methioned by Gerd, we nowuse HuaWei  Kunpeng-920 machine and the qxl works fine, it is Armv8.2 architecture. In order to make qxl work properly on arm64, the other modification I made are onqemu.https://lore.kernel.org/all/20220318085931.3899316-1-liuco...@kylinos.cn/Regards,Cong.
        主 题:Re: [PATCH v1 1/2] drm/qxl: replace ioremap by ioremap_cache on arm64
            日 期:2022-03-23 18:26
            发件人:Robin Murphy
            收件人:Gerd Hoffmann
            
        
        On 2022-03-23 10:11, Gerd Hoffmann wrote:> On Wed, Mar 23, 2022 at 09:45:13AM +, Robin Murphy wrote:>> On 2022-03-23 07:15, Christian K�nig wrote:>>> Am 22.03.22 um 10:34 schrieb Cong Liu: qxl use ioremap to map ram_header and rom, in the arm64 implementation, the device is mapped as DEVICE_nGnRE, it can not support unaligned access.>> Well that some ARM boards doesn't allow unaligned access to MMIO space>>> is a well known bug of those ARM boards.>> So as far as I know this is a hardware bug you are trying to workaround>>> here and I'm not 100% sure that this is correct. No, this one's not a bug. The Device memory type used for iomem mappings is>> *architecturally* defined to enforce properties like aligned accesses, no>> speculation, no reordering, etc. If something wants to be treated more like>> RAM than actual MMIO registers, then ioremap_wc() or ioremap_cache() is the>> appropriate thing to do in general (with the former being a bit more>> portable according to Documentation/driver-api/device-io.rst).> > Well, qxl is a virtual device, so it *is* ram.> > I'm wondering whenever qxl actually works on arm?  As far I know all> virtual display devices with (virtual) pci memory bars for vram do not> work on arm due to the guest mapping vram as io memory and the host> mapping vram as normal ram and the mapping attribute mismatch causes> caching troubles (only noticeable on real arm hardware, not in> emulation).  Did something change here recently?Indeed, Armv8.4 introduced the S2FWB feature to cope with situations like this - essentially it allows the hypervisor to share RAM-backed pages with the guest without losing coherency regardless of how the guest maps them.Robin.

[PATCH v1] drm: omapdrm: Check for NULL return of kzalloc()

2022-03-25 Thread QintaoShen
kzalloc() is a memory allocation function which may return NULL.
It is better to check the return value of it to catch the error in time.

Signed-off-by: QintaoShen 
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 3 +++
 drivers/gpu/drm/omapdrm/omap_irq.c  | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c 
b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 06a719c..fcd76ea 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -166,6 +166,9 @@ void omap_crtc_set_enabled(struct drm_crtc *crtc, bool 
enable)
dispc_mgr_enable(priv->dispc, channel, enable);
omap_crtc->enabled = enable;
 
+   if (!wait)
+   return ;
+
ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100));
if (ret) {
dev_err(dev->dev, "%s: timeout waiting for %s\n",
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c 
b/drivers/gpu/drm/omapdrm/omap_irq.c
index 4aca14d..a234462 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -45,6 +45,9 @@ struct omap_irq_wait * omap_irq_wait_init(struct drm_device 
*dev,
struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL);
unsigned long flags;
 
+   if (!wait)
+   return NULL;
+
init_waitqueue_head(&wait->wq);
wait->irqmask = irqmask;
wait->count = count;
-- 
2.7.4



[PATCH] drm: gma500: clean up some style problems reported by checkpatch.pl

2022-03-25 Thread Haowen Bai
WARNING: Statements should start on a tabstop

WARNING: Missing a blank line after declarations

Signed-off-by: Haowen Bai 
---
 drivers/gpu/drm/gma500/mid_bios.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/gma500/mid_bios.c 
b/drivers/gpu/drm/gma500/mid_bios.c
index 7e76790..71942c2 100644
--- a/drivers/gpu/drm/gma500/mid_bios.c
+++ b/drivers/gpu/drm/gma500/mid_bios.c
@@ -50,8 +50,8 @@ static void mid_get_fuse_settings(struct drm_device *dev)
DRM_INFO("internal display is %s\n",
 dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display");
 
-/* Prevent runtime suspend at start*/
-if (dev_priv->iLVDS_enable) {
+   /* Prevent runtime suspend at start*/
+   if (dev_priv->iLVDS_enable) {
dev_priv->is_lvds_on = true;
dev_priv->is_mipi_on = false;
} else {
@@ -325,6 +325,7 @@ static void mid_get_vbt_data(struct drm_psb_private 
*dev_priv)
 int mid_chip_setup(struct drm_device *dev)
 {
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+
mid_get_fuse_settings(dev);
mid_get_vbt_data(dev_priv);
mid_get_pci_revID(dev_priv);
-- 
2.7.4



Re: [PATCH v3 6/6] drm/msm: make mdp5/dpu devices master components

2022-03-25 Thread Dmitry Baryshkov

On 25/03/2022 00:37, Stephen Boyd wrote:

Quoting Dmitry Baryshkov (2022-03-23 02:25:38)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 38627ccf3068..ab8a35e09bc9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -381,8 +381,8 @@ static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms 
*dpu_kms)
 struct icc_path *path1;
 struct drm_device *dev = dpu_kms->dev;

-   path0 = of_icc_get(dev->dev, "mdp0-mem");
-   path1 = of_icc_get(dev->dev, "mdp1-mem");
+   path0 = of_icc_get(dev->dev->parent, "mdp0-mem");


dev->dev->parent is long


+   path1 = of_icc_get(dev->dev->parent, "mdp1-mem");

 if (IS_ERR_OR_NULL(path0))
 return PTR_ERR_OR_ZERO(path0);
@@ -837,6 +837,9 @@ static void dpu_kms_destroy(struct msm_kms *kms)
 _dpu_kms_hw_destroy(dpu_kms);

 msm_kms_destroy(&dpu_kms->base);
+
+   if (dpu_kms->rpm_enabled)
+   pm_runtime_disable(&dpu_kms->pdev->dev);
  }

  static irqreturn_t dpu_irq(struct msm_kms *kms)
@@ -978,7 +981,7 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms)
 if (!domain)
 return 0;

-   mmu = msm_iommu_new(dpu_kms->dev->dev, domain);
+   mmu = msm_iommu_new(dpu_kms->dev->dev->parent, domain);


And dpu_kms->dev->dev->parent is longer. Can we get some local variable
or something that is more descriptive? I guess it is an 'mdss_dev'?


Yes, I'll fix these two usages.




 if (IS_ERR(mmu)) {
 iommu_domain_free(domain);
 return PTR_ERR(mmu);
@@ -1172,40 +1175,15 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
 return rc;
  }

-static int dpu_kms_init(struct drm_device *dev)
-{
-   struct msm_drm_private *priv;
-   struct dpu_kms *dpu_kms;
-   int irq;
-
-   if (!dev) {
-   DPU_ERROR("drm device node invalid\n");
-   return -EINVAL;
-   }
-
-   priv = dev->dev_private;
-   dpu_kms = to_dpu_kms(priv->kms);
-
-   irq = irq_of_parse_and_map(dpu_kms->pdev->dev.of_node, 0);
-   if (irq < 0) {
-   DPU_ERROR("failed to get irq: %d\n", irq);
-   return irq;
-   }
-   dpu_kms->base.irq = irq;
-
-   return 0;
-}
-
-static int dpu_bind(struct device *dev, struct device *master, void *data)
+static int dpu_kms_init(struct drm_device *ddev)
  {
-   struct msm_drm_private *priv = dev_get_drvdata(master);
+   struct msm_drm_private *priv = ddev->dev_private;
+   struct device *dev = ddev->dev;
 struct platform_device *pdev = to_platform_device(dev);
-   struct drm_device *ddev = priv->dev;
 struct dpu_kms *dpu_kms;
+   int irq;
 int ret = 0;

-   priv->kms_init = dpu_kms_init;
-
 dpu_kms = devm_kzalloc(&pdev->dev, sizeof(*dpu_kms), GFP_KERNEL);
 if (!dpu_kms)
 return -ENOMEM;
@@ -1227,8 +1205,6 @@ static int dpu_bind(struct device *dev, struct device 
*master, void *data)
 }
 dpu_kms->num_clocks = ret;

-   platform_set_drvdata(pdev, dpu_kms);
-
 ret = msm_kms_init(&dpu_kms->base, &kms_funcs);
 if (ret) {
 DPU_ERROR("failed to init kms, ret=%d\n", ret);
@@ -1242,31 +1218,25 @@ static int dpu_bind(struct device *dev, struct device 
*master, void *data)

 priv->kms = &dpu_kms->base;

-   return ret;
-}
-
-static void dpu_unbind(struct device *dev, struct device *master, void *data)
-{
-   struct platform_device *pdev = to_platform_device(dev);
-   struct dpu_kms *dpu_kms = platform_get_drvdata(pdev);
+   irq = irq_of_parse_and_map(dpu_kms->pdev->dev.of_node, 0);


Why doesn't platform_get_irq() work? This is code movement but I'm
trying to understand why OF APIs are required.


Good question, I'll take a look separately (in a followup patch).




+   if (irq < 0) {
+   DPU_ERROR("failed to get irq: %d\n", irq);
+   return irq;
+   }
+   dpu_kms->base.irq = irq;

-   if (dpu_kms->rpm_enabled)
-   pm_runtime_disable(&pdev->dev);
+   return 0;
  }

diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 1f571372e928..ab25fff271f9 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -194,9 +194,6 @@ static inline void msm_kms_destroy(struct msm_kms *kms)
 msm_atomic_destroy_pending_timer(&kms->pending_timers[i]);
  }

-extern const struct of_device_id dpu_dt_match[];
-extern const struct of_device_id mdp5_dt_match[];
-
  #define for_each_crtc_mask(dev, crtc, crtc_mask) \
 drm_for_each_crtc(crtc, dev) \
 for_each_if (drm_crtc_mask(crtc) & (crtc_mask))
diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index 7451105cbf01..9ecae833037d 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@

[PATCH] drm/i915/uapi: Document DRM_I915_QUERY_HWCONFIG_BLOB

2022-03-25 Thread Tvrtko Ursulin
From: Tvrtko Ursulin 

UAPI with absolutely no documentation should not have been added -
clarify blob format and content will be described externally.

Fixes: 78e1fb3112c0 ("drm/i915/uapi: Add query for hwconfig blob")
Signed-off-by: Tvrtko Ursulin 
Co-developed-by: Jordan Justen 
Cc: Jon Bloomfield 
Cc: Daniel Vetter 
Cc: John Harrison 
Cc: Jon Ewins 
Cc: Joonas Lahtinen 
Cc: Rodrigo Vivi 
---
 include/uapi/drm/i915_drm.h | 13 +
 1 file changed, 13 insertions(+)

diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 071ffd9d51f1..8d0719bee8fc 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -2683,6 +2683,9 @@ struct drm_i915_perf_oa_config {
  *
  * The behaviour is determined by the @query_id. Note that exactly what
  * @data_ptr is also depends on the specific @query_id.
+ *
+ * For specific queries see:
+ *  * `GuC HWCONFIG blob uAPI`_
  */
 struct drm_i915_query_item {
/** @query_id: The id for this query */
@@ -3135,6 +3138,16 @@ struct drm_i915_query_memory_regions {
struct drm_i915_memory_region_info regions[];
 };
 
+/**
+ * DOC: GuC HWCONFIG blob uAPI
+ *
+ * The GuC produces a blob with information about the current device.
+ * i915 reads this blob from GuC and makes it available via this uAPI.
+ *
+ * The format and meading of the blob content are documented in the
+ * Programmer's Reference Manual.
+ */
+
 /**
  * struct drm_i915_gem_create_ext - Existing gem_create behaviour, with added
  * extension support using struct i915_user_extension.
-- 
2.32.0



Re: [PATCH v2 3/25] drm/amdgpu: Disable ABM when AC mode

2022-03-25 Thread Daniel Vetter
On Fri, Mar 25, 2022 at 08:22:29AM +0100, Christian König wrote:
> Hi Ryan,
> 
> we should try to avoid that and if it isn't possible at least use some
> constant like ACPI_AC_CLASS.
> 
> Could be that the information isn't available otherwise. Alex should know
> more about that.

I wonder whether we shouldn't need a more dedicated notification from acpi
for power supply events instead of stitching this together ourselves. At
least this kind of stuff feels more into the policy/tuning territory where
a bit more careful interfaces might be good instead of just "hey there's
this very funny acpi protocol we just have to take part in to not upset
the hw/fw".
-Daniel

> 
> Regards,
> Christian.
> 
> Am 25.03.22 um 08:09 schrieb Lin, Tsung-hua (Ryan):
> > [AMD Official Use Only]
> > 
> > Hi Christian,
> > 
> > There is already a string comparison in the same function. I just reference 
> > that to port this solution.
> > 
> > 
> > 
> > #define ACPI_AC_CLASS   "ac_adapter"
> > 
> > 
> > static int amdgpu_acpi_event(struct notifier_block *nb,
> >  unsigned long val,
> >  void *data)
> > {
> > struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, 
> > acpi_nb);
> > struct acpi_bus_event *entry = (struct acpi_bus_event *)data;
> > 
> > +   if (strcmp(entry->device_class, "battery") == 0) {
> > +   adev->pm.ac_power = power_supply_is_system_supplied() > 0;
> > +   }
> > 
> > if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) {  
> > <---here!
> > if (power_supply_is_system_supplied() > 0)
> > DRM_DEBUG_DRIVER("pm: AC\n");
> > else
> > DRM_DEBUG_DRIVER("pm: DC\n");
> > 
> > amdgpu_pm_acpi_event_handler(adev);
> > }
> > 
> > /* Check for pending SBIOS requests */
> > return amdgpu_atif_handler(adev, entry);
> > }
> > 
> > Thanks,
> > Ryan Lin.
> > 
> > -Original Message-
> > From: Koenig, Christian 
> > Sent: Friday, March 25, 2022 2:58 PM
> > To: Lin, Tsung-hua (Ryan) ; Wentland, Harry 
> > ; Li, Sun peng (Leo) ; Deucher, 
> > Alexander ; david1.z...@amd.com; 
> > airl...@linux.ie; dan...@ffwll.ch; seanp...@chromium.org; 
> > b...@basnieuwenhuizen.nl; Kazlauskas, Nicholas 
> > ; sas...@kernel.org; markyac...@google.com; 
> > victorchengchi...@amd.com; ching-shih...@amd.corp-partner.google.com; 
> > Siqueira, Rodrigo ; ddavenp...@chromium.org; 
> > amd-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; 
> > linux-ker...@vger.kernel.org; Li, Leon 
> > Subject: Re: [PATCH v2 3/25] drm/amdgpu: Disable ABM when AC mode
> > 
> > Am 25.03.22 um 05:05 schrieb Ryan Lin:
> > > Disable ABM feature when the system is running on AC mode to get the
> > > more perfect contrast of the display.
> > > 
> > > Signed-off-by: Ryan Lin 
> > > 
> > > ---
> > >drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c  |  4 ++
> > >drivers/gpu/drm/amd/amdgpu/amdgpu_device.c|  1 +
> > >drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c | 58 ---
> > >drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h   |  1 +
> > >4 files changed, 42 insertions(+), 22 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> > > index c560c1ab62ecb..bc8bb9aad2e36 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> > > @@ -822,6 +822,10 @@ static int amdgpu_acpi_event(struct notifier_block 
> > > *nb,
> > >   struct amdgpu_device *adev = container_of(nb, struct 
> > > amdgpu_device, acpi_nb);
> > >   struct acpi_bus_event *entry = (struct acpi_bus_event *)data;
> > > + if (strcmp(entry->device_class, "battery") == 0) {
> > String comparison in a hot path is not something we usually like to see in 
> > the kernel.
> > 
> > Isn't there any other way to detect that? Like a flag or similar?
> > 
> > Regards,
> > Christian.
> > 
> > > + adev->pm.ac_power = power_supply_is_system_supplied() > 0;
> > > + }
> > > +
> > >   if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) {
> > >   if (power_supply_is_system_supplied() > 0)
> > >   DRM_DEBUG_DRIVER("pm: AC\n");
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> > > index abfcc1304ba0c..3a0afe7602727 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> > > @@ -3454,6 +3454,7 @@ int amdgpu_device_init(struct amdgpu_device
> > > *adev,
> > >   adev->gfx.gfx_off_req_count = 1;
> > >   adev->pm.ac_power = power_supply_is_system_supplied() > 0;
> > > + adev->pm.old_ac_power = true;
> > >   atomic_set(&adev->throttling_logging_enabled, 1);
> > >   /*
> > > diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
> > > b/drivers/gpu/

Re: [PATCH] drm/i915/uapi: Document DRM_I915_QUERY_HWCONFIG_BLOB

2022-03-25 Thread Daniel Vetter
On Fri, Mar 25, 2022 at 09:49:16AM +, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin 
> 
> UAPI with absolutely no documentation should not have been added -
> clarify blob format and content will be described externally.
> 
> Fixes: 78e1fb3112c0 ("drm/i915/uapi: Add query for hwconfig blob")
> Signed-off-by: Tvrtko Ursulin 
> Co-developed-by: Jordan Justen 
> Cc: Jon Bloomfield 
> Cc: Daniel Vetter 
> Cc: John Harrison 
> Cc: Jon Ewins 
> Cc: Joonas Lahtinen 
> Cc: Rodrigo Vivi 
> ---
>  include/uapi/drm/i915_drm.h | 13 +
>  1 file changed, 13 insertions(+)
> 
> diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
> index 071ffd9d51f1..8d0719bee8fc 100644
> --- a/include/uapi/drm/i915_drm.h
> +++ b/include/uapi/drm/i915_drm.h
> @@ -2683,6 +2683,9 @@ struct drm_i915_perf_oa_config {
>   *
>   * The behaviour is determined by the @query_id. Note that exactly what
>   * @data_ptr is also depends on the specific @query_id.
> + *
> + * For specific queries see:
> + *  * `GuC HWCONFIG blob uAPI`_

I'd put this into the @query_id section, and then make it an item list
with the #define as the label, so that it becomes tidy and can neatly
iterate them all.

Anyway we can bikeshed this all more in a follow-up.

Reviewed-by: Daniel Vetter 

>   */
>  struct drm_i915_query_item {
>   /** @query_id: The id for this query */
> @@ -3135,6 +3138,16 @@ struct drm_i915_query_memory_regions {
>   struct drm_i915_memory_region_info regions[];
>  };
>  
> +/**
> + * DOC: GuC HWCONFIG blob uAPI
> + *
> + * The GuC produces a blob with information about the current device.
> + * i915 reads this blob from GuC and makes it available via this uAPI.
> + *
> + * The format and meading of the blob content are documented in the
> + * Programmer's Reference Manual.
> + */
> +
>  /**
>   * struct drm_i915_gem_create_ext - Existing gem_create behaviour, with added
>   * extension support using struct i915_user_extension.
> -- 
> 2.32.0
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


Re: [PATCH v2 3/25] drm/amdgpu: Disable ABM when AC mode

2022-03-25 Thread Christian König

Am 25.03.22 um 10:49 schrieb Daniel Vetter:

On Fri, Mar 25, 2022 at 08:22:29AM +0100, Christian König wrote:

Hi Ryan,

we should try to avoid that and if it isn't possible at least use some
constant like ACPI_AC_CLASS.

Could be that the information isn't available otherwise. Alex should know
more about that.

I wonder whether we shouldn't need a more dedicated notification from acpi
for power supply events instead of stitching this together ourselves. At
least this kind of stuff feels more into the policy/tuning territory where
a bit more careful interfaces might be good instead of just "hey there's
this very funny acpi protocol we just have to take part in to not upset
the hw/fw".


That is pretty much my thinking as well.

A quick grep shows that both amdgpu, radeon, nouveau and i915 all parse 
the same information with self defined macros and strcmp(). That's not 
really the way we usually do stuff like this.


Ideally the ACPI layer in the core kernel would parse the information 
and give it as enum or flags to the drivers instead.


At bare minimum we should move all the ACPI_AC_CLASS, ACPI_VIDEO_CLASS 
and raw strings into a common place to start with.


Regards,
Christian.


-Daniel


Regards,
Christian.

Am 25.03.22 um 08:09 schrieb Lin, Tsung-hua (Ryan):

[AMD Official Use Only]

Hi Christian,

There is already a string comparison in the same function. I just reference 
that to port this solution.



#define ACPI_AC_CLASS   "ac_adapter"


static int amdgpu_acpi_event(struct notifier_block *nb,
 unsigned long val,
 void *data)
{
struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, 
acpi_nb);
struct acpi_bus_event *entry = (struct acpi_bus_event *)data;

+   if (strcmp(entry->device_class, "battery") == 0) {
+   adev->pm.ac_power = power_supply_is_system_supplied() > 0;
+   }

if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) {  
<---here!
if (power_supply_is_system_supplied() > 0)
DRM_DEBUG_DRIVER("pm: AC\n");
else
DRM_DEBUG_DRIVER("pm: DC\n");

amdgpu_pm_acpi_event_handler(adev);
}

/* Check for pending SBIOS requests */
return amdgpu_atif_handler(adev, entry);
}

Thanks,
Ryan Lin.

-Original Message-
From: Koenig, Christian 
Sent: Friday, March 25, 2022 2:58 PM
To: Lin, Tsung-hua (Ryan) ; Wentland, Harry ; Li, Sun peng 
(Leo) ; Deucher, Alexander ; david1.z...@amd.com; 
airl...@linux.ie; dan...@ffwll.ch; seanp...@chromium.org; b...@basnieuwenhuizen.nl; Kazlauskas, Nicholas 
; sas...@kernel.org; markyac...@google.com; victorchengchi...@amd.com; 
ching-shih...@amd.corp-partner.google.com; Siqueira, Rodrigo ; ddavenp...@chromium.org; 
amd-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; linux-ker...@vger.kernel.org; Li, Leon 

Subject: Re: [PATCH v2 3/25] drm/amdgpu: Disable ABM when AC mode

Am 25.03.22 um 05:05 schrieb Ryan Lin:

Disable ABM feature when the system is running on AC mode to get the
more perfect contrast of the display.

Signed-off-by: Ryan Lin 

---
drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c  |  4 ++
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c|  1 +
drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c | 58 ---
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h   |  1 +
4 files changed, 42 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index c560c1ab62ecb..bc8bb9aad2e36 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -822,6 +822,10 @@ static int amdgpu_acpi_event(struct notifier_block *nb,
struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, 
acpi_nb);
struct acpi_bus_event *entry = (struct acpi_bus_event *)data;
+   if (strcmp(entry->device_class, "battery") == 0) {

String comparison in a hot path is not something we usually like to see in the 
kernel.

Isn't there any other way to detect that? Like a flag or similar?

Regards,
Christian.


+   adev->pm.ac_power = power_supply_is_system_supplied() > 0;
+   }
+
if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) {
if (power_supply_is_system_supplied() > 0)
DRM_DEBUG_DRIVER("pm: AC\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index abfcc1304ba0c..3a0afe7602727 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -3454,6 +3454,7 @@ int amdgpu_device_init(struct amdgpu_device
*adev,
adev->gfx.gfx_off_req_count = 1;
adev->pm.ac_power = power_supply_is_system_supplied() > 0;
+   adev->pm.old_ac_power = true;
atomic_set(&adev->throttling_logging_enabled

Re: [PATCH 1/2] drm/i915/ttm: limit where we apply TTM_PL_FLAG_CONTIGUOUS

2022-03-25 Thread Das, Nirmoy



On 3/25/2022 8:16 AM, Thomas Hellström wrote:


On 3/24/22 18:21, Matthew Auld wrote:

We only need this when allocating device local-memory, where this
influences the drm_buddy. Currently there is some funny behaviour where
an "in limbo" system memory object is lacking the relevant placement
flags etc. before we first allocate the ttm_tt, leading to ttm
performing a move when not needed, since the current placement is seen
as not compatible.

Suggested-by: Thomas Hellström 
Fixes: 2ed38cec5606 ("drm/i915: opportunistically apply 
ALLOC_CONTIGIOUS")

Signed-off-by: Matthew Auld 
Cc: Nirmoy Das 
---
  drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c 
b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c

index e4a06fcf741a..97e648fa76bd 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -133,6 +133,9 @@ i915_ttm_place_from_region(const struct 
intel_memory_region *mr,

  memset(place, 0, sizeof(*place));
  place->mem_type = intel_region_to_ttm_type(mr);
  +    if (mr->type == INTEL_MEMORY_SYSTEM)
+    return;
+


Reviewed-by: Thomas Hellström 



Reviewed-by: Nirmoy Das 





  if (flags & I915_BO_ALLOC_CONTIGUOUS)
  place->flags |= TTM_PL_FLAG_CONTIGUOUS;
  if (offset != I915_BO_INVALID_OFFSET) {


Re: [PATCH 1/2] dma-buf: add dma_fence_unwrap

2022-03-25 Thread Daniel Vetter
On Fri, Mar 11, 2022 at 12:02:43PM +0100, Christian König wrote:
> Add a general purpose helper to deep dive into dma_fence_chain/dma_fence_array
> structures and iterate over all the fences in them.
> 
> This is useful when we need to flatten out all fences in those structures.
> 
> Signed-off-by: Christian König 
> ---
>  Documentation/driver-api/dma-buf.rst  |   6 +
>  drivers/dma-buf/Makefile  |   1 +
>  drivers/dma-buf/selftests.h   |   1 +
>  drivers/dma-buf/st-dma-fence-unwrap.c | 279 ++
>  include/linux/dma-fence-unwrap.h  |  99 +
>  5 files changed, 386 insertions(+)
>  create mode 100644 drivers/dma-buf/st-dma-fence-unwrap.c
>  create mode 100644 include/linux/dma-fence-unwrap.h
> 
> diff --git a/Documentation/driver-api/dma-buf.rst 
> b/Documentation/driver-api/dma-buf.rst
> index 2cd7db82d9fe..7209500f08c8 100644
> --- a/Documentation/driver-api/dma-buf.rst
> +++ b/Documentation/driver-api/dma-buf.rst
> @@ -194,6 +194,12 @@ DMA Fence Chain
>  .. kernel-doc:: include/linux/dma-fence-chain.h
> :internal:
>  
> +DMA Fence unwrap
> +
> +
> +.. kernel-doc:: include/linux/dma-fence-unwrap.h
> +   :internal:
> +
>  DMA Fence uABI/Sync File
>  
>  
> diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
> index 511805dbeb75..4c9eb53ba3f8 100644
> --- a/drivers/dma-buf/Makefile
> +++ b/drivers/dma-buf/Makefile
> @@ -12,6 +12,7 @@ dmabuf_selftests-y := \
>   selftest.o \
>   st-dma-fence.o \
>   st-dma-fence-chain.o \
> + st-dma-fence-unwrap.o \
>   st-dma-resv.o
>  
>  obj-$(CONFIG_DMABUF_SELFTESTS)   += dmabuf_selftests.o
> diff --git a/drivers/dma-buf/selftests.h b/drivers/dma-buf/selftests.h
> index 97d73aaa31da..851965867d9c 100644
> --- a/drivers/dma-buf/selftests.h
> +++ b/drivers/dma-buf/selftests.h
> @@ -12,4 +12,5 @@
>  selftest(sanitycheck, __sanitycheck__) /* keep first (igt selfcheck) */
>  selftest(dma_fence, dma_fence)
>  selftest(dma_fence_chain, dma_fence_chain)
> +selftest(dma_fence_unwrap, dma_fence_unwrap)
>  selftest(dma_resv, dma_resv)
> diff --git a/drivers/dma-buf/st-dma-fence-unwrap.c 
> b/drivers/dma-buf/st-dma-fence-unwrap.c
> new file mode 100644
> index ..d821faaebe93
> --- /dev/null
> +++ b/drivers/dma-buf/st-dma-fence-unwrap.c
> @@ -0,0 +1,279 @@
> +// SPDX-License-Identifier: MIT
> +
> +/*
> + * Copyright (C) 2022 Advanced Micro Devices, Inc.
> + */
> +
> +#include 
> +#if 0
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#endif
> +
> +#include "selftest.h"
> +
> +#define CHAIN_SZ (4 << 10)
> +
> +static struct kmem_cache *slab_fences;

Your own slab feels a bit like overkill. kmalloc/kfree not good enough?

> +
> +static inline struct mock_fence {
> + struct dma_fence base;
> + spinlock_t lock;
> +} *to_mock_fence(struct dma_fence *f) {
> + return container_of(f, struct mock_fence, base);
> +}
> +
> +static const char *mock_name(struct dma_fence *f)
> +{
> + return "mock";
> +}
> +
> +static void mock_fence_release(struct dma_fence *f)
> +{
> + kmem_cache_free(slab_fences, to_mock_fence(f));
> +}
> +
> +static const struct dma_fence_ops mock_ops = {
> + .get_driver_name = mock_name,
> + .get_timeline_name = mock_name,
> + .release = mock_fence_release,
> +};
> +
> +static struct dma_fence *mock_fence(void)
> +{
> + struct mock_fence *f;
> +
> + f = kmem_cache_alloc(slab_fences, GFP_KERNEL);
> + if (!f)
> + return NULL;
> +
> + spin_lock_init(&f->lock);
> + dma_fence_init(&f->base, &mock_ops, &f->lock, 0, 0);
> +
> + return &f->base;
> +}
> +
> +static struct dma_fence *mock_array(unsigned int num_fences, ...)
> +{
> + struct dma_fence_array *array;
> + struct dma_fence **fences;
> + va_list valist;
> + int i;
> +
> + fences = kcalloc(num_fences, sizeof(*fences), GFP_KERNEL);
> + if (!fences)
> + return NULL;
> +
> + va_start(valist, num_fences);
> + for (i = 0; i < num_fences; ++i)
> + fences[i] = va_arg(valist, typeof(*fences));
> + va_end(valist);
> +
> + array = dma_fence_array_create(num_fences, fences,
> +dma_fence_context_alloc(1),
> +1, false);
> + if (!array)
> + goto cleanup;
> + return &array->base;
> +
> +cleanup:
> + for (i = 0; i < num_fences; ++i)
> + dma_fence_put(fences[i]);
> + kfree(fences);
> + return NULL;
> +}
> +
> +static struct dma_fence *mock_chain(struct dma_fence *prev,
> + struct dma_fence *fence)
> +{
> + struct dma_fence_chain *f;
> +
> + f = dma_fence_chain_alloc();
> + if (!f) {
> + dma_fence_put(prev);
> + dma_fence_put(fence);
> + return NULL;
> + }
> +
> + dma_fence_chain_init(f, prev, fence, 1);
> + return &f->bas

Re: [Intel-gfx] [PATCH 1/2] drm/i915/ttm: limit where we apply TTM_PL_FLAG_CONTIGUOUS

2022-03-25 Thread Das, Nirmoy



On 3/25/2022 11:03 AM, Das, Nirmoy wrote:

Reviewed-by: Nirmoy Das 
Sorry, I meant this r-b for the  2nd patch and for this one Acked-by: 
Nirmoy Das 


Re: [PATCH 1/2] dma-buf: add dma_fence_unwrap

2022-03-25 Thread Daniel Vetter
On Fri, Mar 25, 2022 at 11:03:54AM +0100, Daniel Vetter wrote:
> On Fri, Mar 11, 2022 at 12:02:43PM +0100, Christian König wrote:
> > Add a general purpose helper to deep dive into 
> > dma_fence_chain/dma_fence_array
> > structures and iterate over all the fences in them.
> > 
> > This is useful when we need to flatten out all fences in those structures.
> > 
> > Signed-off-by: Christian König 
> > ---
> >  Documentation/driver-api/dma-buf.rst  |   6 +
> >  drivers/dma-buf/Makefile  |   1 +
> >  drivers/dma-buf/selftests.h   |   1 +
> >  drivers/dma-buf/st-dma-fence-unwrap.c | 279 ++
> >  include/linux/dma-fence-unwrap.h  |  99 +
> >  5 files changed, 386 insertions(+)
> >  create mode 100644 drivers/dma-buf/st-dma-fence-unwrap.c
> >  create mode 100644 include/linux/dma-fence-unwrap.h
> > 
> > diff --git a/Documentation/driver-api/dma-buf.rst 
> > b/Documentation/driver-api/dma-buf.rst
> > index 2cd7db82d9fe..7209500f08c8 100644
> > --- a/Documentation/driver-api/dma-buf.rst
> > +++ b/Documentation/driver-api/dma-buf.rst
> > @@ -194,6 +194,12 @@ DMA Fence Chain
> >  .. kernel-doc:: include/linux/dma-fence-chain.h
> > :internal:
> >  
> > +DMA Fence unwrap
> > +
> > +
> > +.. kernel-doc:: include/linux/dma-fence-unwrap.h
> > +   :internal:

Ok I forgot one bikeshed: I'd just include this in dma-fence-chain.h and
maybe go with the dma_fence_chain_unwrap_ prefix for everything. That
makes it even more clearer that the two are meant to go together. Plus ofc
the link from struct dma_fence_chain to this iterator in the docs too.

Or I'm just not understanding why you made this a separate thing?
-Daniel

> > +
> >  DMA Fence uABI/Sync File
> >  
> >  
> > diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
> > index 511805dbeb75..4c9eb53ba3f8 100644
> > --- a/drivers/dma-buf/Makefile
> > +++ b/drivers/dma-buf/Makefile
> > @@ -12,6 +12,7 @@ dmabuf_selftests-y := \
> > selftest.o \
> > st-dma-fence.o \
> > st-dma-fence-chain.o \
> > +   st-dma-fence-unwrap.o \
> > st-dma-resv.o
> >  
> >  obj-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o
> > diff --git a/drivers/dma-buf/selftests.h b/drivers/dma-buf/selftests.h
> > index 97d73aaa31da..851965867d9c 100644
> > --- a/drivers/dma-buf/selftests.h
> > +++ b/drivers/dma-buf/selftests.h
> > @@ -12,4 +12,5 @@
> >  selftest(sanitycheck, __sanitycheck__) /* keep first (igt selfcheck) */
> >  selftest(dma_fence, dma_fence)
> >  selftest(dma_fence_chain, dma_fence_chain)
> > +selftest(dma_fence_unwrap, dma_fence_unwrap)
> >  selftest(dma_resv, dma_resv)
> > diff --git a/drivers/dma-buf/st-dma-fence-unwrap.c 
> > b/drivers/dma-buf/st-dma-fence-unwrap.c
> > new file mode 100644
> > index ..d821faaebe93
> > --- /dev/null
> > +++ b/drivers/dma-buf/st-dma-fence-unwrap.c
> > @@ -0,0 +1,279 @@
> > +// SPDX-License-Identifier: MIT
> > +
> > +/*
> > + * Copyright (C) 2022 Advanced Micro Devices, Inc.
> > + */
> > +
> > +#include 
> > +#if 0
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#endif
> > +
> > +#include "selftest.h"
> > +
> > +#define CHAIN_SZ (4 << 10)
> > +
> > +static struct kmem_cache *slab_fences;
> 
> Your own slab feels a bit like overkill. kmalloc/kfree not good enough?
> 
> > +
> > +static inline struct mock_fence {
> > +   struct dma_fence base;
> > +   spinlock_t lock;
> > +} *to_mock_fence(struct dma_fence *f) {
> > +   return container_of(f, struct mock_fence, base);
> > +}
> > +
> > +static const char *mock_name(struct dma_fence *f)
> > +{
> > +   return "mock";
> > +}
> > +
> > +static void mock_fence_release(struct dma_fence *f)
> > +{
> > +   kmem_cache_free(slab_fences, to_mock_fence(f));
> > +}
> > +
> > +static const struct dma_fence_ops mock_ops = {
> > +   .get_driver_name = mock_name,
> > +   .get_timeline_name = mock_name,
> > +   .release = mock_fence_release,
> > +};
> > +
> > +static struct dma_fence *mock_fence(void)
> > +{
> > +   struct mock_fence *f;
> > +
> > +   f = kmem_cache_alloc(slab_fences, GFP_KERNEL);
> > +   if (!f)
> > +   return NULL;
> > +
> > +   spin_lock_init(&f->lock);
> > +   dma_fence_init(&f->base, &mock_ops, &f->lock, 0, 0);
> > +
> > +   return &f->base;
> > +}
> > +
> > +static struct dma_fence *mock_array(unsigned int num_fences, ...)
> > +{
> > +   struct dma_fence_array *array;
> > +   struct dma_fence **fences;
> > +   va_list valist;
> > +   int i;
> > +
> > +   fences = kcalloc(num_fences, sizeof(*fences), GFP_KERNEL);
> > +   if (!fences)
> > +   return NULL;
> > +
> > +   va_start(valist, num_fences);
> > +   for (i = 0; i < num_fences; ++i)
> > +   fences[i] = va_arg(valist, typeof(*fences));
> > +   va_end(valist);
> > +
> > +   array = dma_fence_array_create(num_fences, fences,
> > +  dma_fence_context_alloc(1),
> > +

Re: [PATCH 1/2] dma-buf: add dma_fence_unwrap

2022-03-25 Thread Christian König

Am 25.03.22 um 11:07 schrieb Daniel Vetter:

On Fri, Mar 25, 2022 at 11:03:54AM +0100, Daniel Vetter wrote:

On Fri, Mar 11, 2022 at 12:02:43PM +0100, Christian König wrote:

Add a general purpose helper to deep dive into dma_fence_chain/dma_fence_array
structures and iterate over all the fences in them.

This is useful when we need to flatten out all fences in those structures.

Signed-off-by: Christian König 
---
  Documentation/driver-api/dma-buf.rst  |   6 +
  drivers/dma-buf/Makefile  |   1 +
  drivers/dma-buf/selftests.h   |   1 +
  drivers/dma-buf/st-dma-fence-unwrap.c | 279 ++
  include/linux/dma-fence-unwrap.h  |  99 +
  5 files changed, 386 insertions(+)
  create mode 100644 drivers/dma-buf/st-dma-fence-unwrap.c
  create mode 100644 include/linux/dma-fence-unwrap.h

diff --git a/Documentation/driver-api/dma-buf.rst 
b/Documentation/driver-api/dma-buf.rst
index 2cd7db82d9fe..7209500f08c8 100644
--- a/Documentation/driver-api/dma-buf.rst
+++ b/Documentation/driver-api/dma-buf.rst
@@ -194,6 +194,12 @@ DMA Fence Chain
  .. kernel-doc:: include/linux/dma-fence-chain.h
 :internal:
  
+DMA Fence unwrap

+
+
+.. kernel-doc:: include/linux/dma-fence-unwrap.h
+   :internal:

Ok I forgot one bikeshed: I'd just include this in dma-fence-chain.h and
maybe go with the dma_fence_chain_unwrap_ prefix for everything. That
makes it even more clearer that the two are meant to go together. Plus ofc
the link from struct dma_fence_chain to this iterator in the docs too.

Or I'm just not understanding why you made this a separate thing?


Well it should be used to unwrap dma_fence_array containers as well and 
I don't really want to add a dependency between dma_fence_chain and 
dma_fence_array.


I've spend quite some work to keep the two containers separated and also 
describe the separate use cases for each.


I can of course add some kerneldoc to let the chain and array 
documentation point to this one here.


Thanks,
Christian.


-Daniel


+
  DMA Fence uABI/Sync File
  
  
diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile

index 511805dbeb75..4c9eb53ba3f8 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -12,6 +12,7 @@ dmabuf_selftests-y := \
selftest.o \
st-dma-fence.o \
st-dma-fence-chain.o \
+   st-dma-fence-unwrap.o \
st-dma-resv.o
  
  obj-$(CONFIG_DMABUF_SELFTESTS)	+= dmabuf_selftests.o

diff --git a/drivers/dma-buf/selftests.h b/drivers/dma-buf/selftests.h
index 97d73aaa31da..851965867d9c 100644
--- a/drivers/dma-buf/selftests.h
+++ b/drivers/dma-buf/selftests.h
@@ -12,4 +12,5 @@
  selftest(sanitycheck, __sanitycheck__) /* keep first (igt selfcheck) */
  selftest(dma_fence, dma_fence)
  selftest(dma_fence_chain, dma_fence_chain)
+selftest(dma_fence_unwrap, dma_fence_unwrap)
  selftest(dma_resv, dma_resv)
diff --git a/drivers/dma-buf/st-dma-fence-unwrap.c 
b/drivers/dma-buf/st-dma-fence-unwrap.c
new file mode 100644
index ..d821faaebe93
--- /dev/null
+++ b/drivers/dma-buf/st-dma-fence-unwrap.c
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: MIT
+
+/*
+ * Copyright (C) 2022 Advanced Micro Devices, Inc.
+ */
+
+#include 
+#if 0
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#endif
+
+#include "selftest.h"
+
+#define CHAIN_SZ (4 << 10)
+
+static struct kmem_cache *slab_fences;

Your own slab feels a bit like overkill. kmalloc/kfree not good enough?


+
+static inline struct mock_fence {
+   struct dma_fence base;
+   spinlock_t lock;
+} *to_mock_fence(struct dma_fence *f) {
+   return container_of(f, struct mock_fence, base);
+}
+
+static const char *mock_name(struct dma_fence *f)
+{
+   return "mock";
+}
+
+static void mock_fence_release(struct dma_fence *f)
+{
+   kmem_cache_free(slab_fences, to_mock_fence(f));
+}
+
+static const struct dma_fence_ops mock_ops = {
+   .get_driver_name = mock_name,
+   .get_timeline_name = mock_name,
+   .release = mock_fence_release,
+};
+
+static struct dma_fence *mock_fence(void)
+{
+   struct mock_fence *f;
+
+   f = kmem_cache_alloc(slab_fences, GFP_KERNEL);
+   if (!f)
+   return NULL;
+
+   spin_lock_init(&f->lock);
+   dma_fence_init(&f->base, &mock_ops, &f->lock, 0, 0);
+
+   return &f->base;
+}
+
+static struct dma_fence *mock_array(unsigned int num_fences, ...)
+{
+   struct dma_fence_array *array;
+   struct dma_fence **fences;
+   va_list valist;
+   int i;
+
+   fences = kcalloc(num_fences, sizeof(*fences), GFP_KERNEL);
+   if (!fences)
+   return NULL;
+
+   va_start(valist, num_fences);
+   for (i = 0; i < num_fences; ++i)
+   fences[i] = va_arg(valist, typeof(*fences));
+   va_end(valist);
+
+   array = dma_fence_array_create(num_fences, fences,
+  dma_fence_context_alloc(1),
+   

Re: [PATCH 2/2] dma-buf/sync-file: fix warning about fence containers

2022-03-25 Thread Daniel Vetter
On Fri, Mar 11, 2022 at 12:02:44PM +0100, Christian König wrote:
> The dma_fence_chain containers can show up in sync_files as well resulting in
> warnings that those can't be added to dma_fence_array containers when merging
> multiple sync_files together.
> 
> Solve this by using the dma_fence_unwrap iterator to deep dive into the
> contained fences and then add those flatten out into a dma_fence_array.
> 
> Signed-off-by: Christian König 

I have no idea why we try to keep fences sorted, but oh well it looks like
the merging is done correctly.

Reviewed-by: Daniel Vetter 

> ---
>  drivers/dma-buf/sync_file.c | 141 +++-
>  1 file changed, 73 insertions(+), 68 deletions(-)
> 
> diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c
> index 394e6e1e9686..b8dea4ec123b 100644
> --- a/drivers/dma-buf/sync_file.c
> +++ b/drivers/dma-buf/sync_file.c
> @@ -5,6 +5,7 @@
>   * Copyright (C) 2012 Google, Inc.
>   */
>  
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -172,20 +173,6 @@ static int sync_file_set_fence(struct sync_file 
> *sync_file,
>   return 0;
>  }
>  
> -static struct dma_fence **get_fences(struct sync_file *sync_file,
> -  int *num_fences)
> -{
> - if (dma_fence_is_array(sync_file->fence)) {
> - struct dma_fence_array *array = 
> to_dma_fence_array(sync_file->fence);
> -
> - *num_fences = array->num_fences;
> - return array->fences;
> - }
> -
> - *num_fences = 1;
> - return &sync_file->fence;
> -}
> -
>  static void add_fence(struct dma_fence **fences,
> int *i, struct dma_fence *fence)
>  {
> @@ -210,86 +197,97 @@ static void add_fence(struct dma_fence **fences,
>  static struct sync_file *sync_file_merge(const char *name, struct sync_file 
> *a,
>struct sync_file *b)
>  {
> + struct dma_fence *a_fence, *b_fence, **fences;
> + struct dma_fence_unwrap a_iter, b_iter;
> + unsigned int index, num_fences;
>   struct sync_file *sync_file;
> - struct dma_fence **fences = NULL, **nfences, **a_fences, **b_fences;
> - int i = 0, i_a, i_b, num_fences, a_num_fences, b_num_fences;
>  
>   sync_file = sync_file_alloc();
>   if (!sync_file)
>   return NULL;
>  
> - a_fences = get_fences(a, &a_num_fences);
> - b_fences = get_fences(b, &b_num_fences);
> - if (a_num_fences > INT_MAX - b_num_fences)
> - goto err;
> + num_fences = 0;
> + dma_fence_unwrap_for_each(a_fence, &a_iter, a->fence)
> + ++num_fences;
> + dma_fence_unwrap_for_each(b_fence, &b_iter, b->fence)
> + ++num_fences;
>  
> - num_fences = a_num_fences + b_num_fences;
> + if (num_fences > INT_MAX)
> + goto err_free_sync_file;
>  
>   fences = kcalloc(num_fences, sizeof(*fences), GFP_KERNEL);
>   if (!fences)
> - goto err;
> + goto err_free_sync_file;
>  
>   /*
> -  * Assume sync_file a and b are both ordered and have no
> -  * duplicates with the same context.
> +  * We can't guarantee that fences in both a and b are ordered, but it is
> +  * still quite likely.
>*
> -  * If a sync_file can only be created with sync_file_merge
> -  * and sync_file_create, this is a reasonable assumption.
> +  * So attempt to order the fences as we pass over them and merge fences
> +  * with the same context.
>*/
> - for (i_a = i_b = 0; i_a < a_num_fences && i_b < b_num_fences; ) {
> - struct dma_fence *pt_a = a_fences[i_a];
> - struct dma_fence *pt_b = b_fences[i_b];
>  
> - if (pt_a->context < pt_b->context) {
> - add_fence(fences, &i, pt_a);
> + index = 0;
> + for (a_fence = dma_fence_unwrap_first(a->fence, &a_iter),
> +  b_fence = dma_fence_unwrap_first(b->fence, &b_iter);
> +  a_fence || b_fence; ) {
> +
> + if (!b_fence) {
> + add_fence(fences, &index, a_fence);
> + a_fence = dma_fence_unwrap_next(&a_iter);
> +
> + } else if (!a_fence) {
> + add_fence(fences, &index, b_fence);
> + b_fence = dma_fence_unwrap_next(&b_iter);
> +
> + } else if (a_fence->context < b_fence->context) {
> + add_fence(fences, &index, a_fence);
> + a_fence = dma_fence_unwrap_next(&a_iter);
>  
> - i_a++;
> - } else if (pt_a->context > pt_b->context) {
> - add_fence(fences, &i, pt_b);
> + } else if (b_fence->context < a_fence->context) {
> + add_fence(fences, &index, b_fence);
> + b_fence = dma_fence_unwrap_next(&b_iter);
> +
> + } else if (__dma_fence_is_later(a_fence->seqno, b_fence->seqno,
> +

Re: [PATCH 1/2] dma-buf: add dma_fence_unwrap

2022-03-25 Thread Daniel Vetter
On Fri, Mar 25, 2022 at 11:10:15AM +0100, Christian König wrote:
> Am 25.03.22 um 11:07 schrieb Daniel Vetter:
> > On Fri, Mar 25, 2022 at 11:03:54AM +0100, Daniel Vetter wrote:
> > > On Fri, Mar 11, 2022 at 12:02:43PM +0100, Christian König wrote:
> > > > Add a general purpose helper to deep dive into 
> > > > dma_fence_chain/dma_fence_array
> > > > structures and iterate over all the fences in them.
> > > > 
> > > > This is useful when we need to flatten out all fences in those 
> > > > structures.
> > > > 
> > > > Signed-off-by: Christian König 
> > > > ---
> > > >   Documentation/driver-api/dma-buf.rst  |   6 +
> > > >   drivers/dma-buf/Makefile  |   1 +
> > > >   drivers/dma-buf/selftests.h   |   1 +
> > > >   drivers/dma-buf/st-dma-fence-unwrap.c | 279 ++
> > > >   include/linux/dma-fence-unwrap.h  |  99 +
> > > >   5 files changed, 386 insertions(+)
> > > >   create mode 100644 drivers/dma-buf/st-dma-fence-unwrap.c
> > > >   create mode 100644 include/linux/dma-fence-unwrap.h
> > > > 
> > > > diff --git a/Documentation/driver-api/dma-buf.rst 
> > > > b/Documentation/driver-api/dma-buf.rst
> > > > index 2cd7db82d9fe..7209500f08c8 100644
> > > > --- a/Documentation/driver-api/dma-buf.rst
> > > > +++ b/Documentation/driver-api/dma-buf.rst
> > > > @@ -194,6 +194,12 @@ DMA Fence Chain
> > > >   .. kernel-doc:: include/linux/dma-fence-chain.h
> > > >  :internal:
> > > > +DMA Fence unwrap
> > > > +
> > > > +
> > > > +.. kernel-doc:: include/linux/dma-fence-unwrap.h
> > > > +   :internal:
> > Ok I forgot one bikeshed: I'd just include this in dma-fence-chain.h and
> > maybe go with the dma_fence_chain_unwrap_ prefix for everything. That
> > makes it even more clearer that the two are meant to go together. Plus ofc
> > the link from struct dma_fence_chain to this iterator in the docs too.
> > 
> > Or I'm just not understanding why you made this a separate thing?
> 
> Well it should be used to unwrap dma_fence_array containers as well and I
> don't really want to add a dependency between dma_fence_chain and
> dma_fence_array.
> 
> I've spend quite some work to keep the two containers separated and also
> describe the separate use cases for each.
> 
> I can of course add some kerneldoc to let the chain and array documentation
> point to this one here.

Yeah I think as a general iterator they should be fine as a separate
thing. Also just realized that we'd need links from both array and chain
to this since it's for both.

The other thing I noticed is that we have dma_fence_chain_for_each()
already. Should we replace all users of that outside of dma-fence-chain.c
with this new thing, and move the chain specific iterator into
dma-fence-chain.c so that it's hidden and people don't make funny
accidents? Just for more safety in this maze, also ofc that's all
follow-up.
-Daniel



> 
> Thanks,
> Christian.
> 
> > -Daniel
> > 
> > > > +
> > > >   DMA Fence uABI/Sync File
> > > >   
> > > > diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
> > > > index 511805dbeb75..4c9eb53ba3f8 100644
> > > > --- a/drivers/dma-buf/Makefile
> > > > +++ b/drivers/dma-buf/Makefile
> > > > @@ -12,6 +12,7 @@ dmabuf_selftests-y := \
> > > > selftest.o \
> > > > st-dma-fence.o \
> > > > st-dma-fence-chain.o \
> > > > +   st-dma-fence-unwrap.o \
> > > > st-dma-resv.o
> > > >   obj-$(CONFIG_DMABUF_SELFTESTS)+= dmabuf_selftests.o
> > > > diff --git a/drivers/dma-buf/selftests.h b/drivers/dma-buf/selftests.h
> > > > index 97d73aaa31da..851965867d9c 100644
> > > > --- a/drivers/dma-buf/selftests.h
> > > > +++ b/drivers/dma-buf/selftests.h
> > > > @@ -12,4 +12,5 @@
> > > >   selftest(sanitycheck, __sanitycheck__) /* keep first (igt selfcheck) 
> > > > */
> > > >   selftest(dma_fence, dma_fence)
> > > >   selftest(dma_fence_chain, dma_fence_chain)
> > > > +selftest(dma_fence_unwrap, dma_fence_unwrap)
> > > >   selftest(dma_resv, dma_resv)
> > > > diff --git a/drivers/dma-buf/st-dma-fence-unwrap.c 
> > > > b/drivers/dma-buf/st-dma-fence-unwrap.c
> > > > new file mode 100644
> > > > index ..d821faaebe93
> > > > --- /dev/null
> > > > +++ b/drivers/dma-buf/st-dma-fence-unwrap.c
> > > > @@ -0,0 +1,279 @@
> > > > +// SPDX-License-Identifier: MIT
> > > > +
> > > > +/*
> > > > + * Copyright (C) 2022 Advanced Micro Devices, Inc.
> > > > + */
> > > > +
> > > > +#include 
> > > > +#if 0
> > > > +#include 
> > > > +#include 
> > > > +#include 
> > > > +#include 
> > > > +#include 
> > > > +#include 
> > > > +#include 
> > > > +#endif
> > > > +
> > > > +#include "selftest.h"
> > > > +
> > > > +#define CHAIN_SZ (4 << 10)
> > > > +
> > > > +static struct kmem_cache *slab_fences;
> > > Your own slab feels a bit like overkill. kmalloc/kfree not good enough?
> > > 
> > > > +
> > > > +static inline struct mock_fence {
> > > > +   struct dma_fence base;
> > > > +   spinlock_t lock;
> > > > +

Re: [PATCH v5 2/4] drm: introduce drm_writeback_connector_init_with_encoder() API

2022-03-25 Thread Liviu Dudau
On Thu, Mar 24, 2022 at 09:36:50AM -0700, Abhinav Kumar wrote:
> Hi Liviu

Hello,

> 
> Thanks for the response.
> 
> On 3/24/2022 3:12 AM, Liviu Dudau wrote:
> > On Wed, Mar 23, 2022 at 11:28:56AM -0700, Abhinav Kumar wrote:
> > > Hi Liviu
> > 
> > Hello,
> > 
> > > 
> > > Thanks for the review.
> > > 
> > > On 3/23/2022 9:46 AM, Liviu Dudau wrote:
> > > > On Mon, Mar 21, 2022 at 04:56:43PM -0700, Abhinav Kumar wrote:
> > > > > For vendors drivers which pass an already allocated and
> > > > > initialized encoder especially for cases where the encoder
> > > > > hardware is shared OR the writeback encoder shares the resources
> > > > > with the rest of the display pipeline introduce a new API,
> > > > > drm_writeback_connector_init_with_encoder() which expects
> > > > > an initialized encoder as a parameter and only sets up the
> > > > > writeback connector.
> > > > > 
> > > > > changes in v5:
> > > > >   - reorder this change to come before in the series
> > > > > to avoid incorrect functionality in subsequent changes
> > > > >   - continue using struct drm_encoder instead of
> > > > > struct drm_encoder * and switch it in next change
> > > > > 
> > > > > Signed-off-by: Abhinav Kumar 
> > > > 
> > > > Hi Abhinav,
> > > > 
> > > > > ---
> > > > >drivers/gpu/drm/drm_writeback.c | 143 
> > > > > 
> > > > >include/drm/drm_writeback.h |   5 ++
> > > > >2 files changed, 106 insertions(+), 42 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/drm_writeback.c 
> > > > > b/drivers/gpu/drm/drm_writeback.c
> > > > > index dc2ef12..abe78b9 100644
> > > > > --- a/drivers/gpu/drm/drm_writeback.c
> > > > > +++ b/drivers/gpu/drm/drm_writeback.c
> > > > > @@ -149,37 +149,15 @@ static const struct drm_encoder_funcs 
> > > > > drm_writeback_encoder_funcs = {
> > > > >   .destroy = drm_encoder_cleanup,
> > > > >};
> > > > > -/**
> > > > > - * drm_writeback_connector_init - Initialize a writeback connector 
> > > > > and its properties
> > > > > - * @dev: DRM device
> > > > > - * @wb_connector: Writeback connector to initialize
> > > > > - * @con_funcs: Connector funcs vtable
> > > > > - * @enc_helper_funcs: Encoder helper funcs vtable to be used by the 
> > > > > internal encoder
> > > > > - * @formats: Array of supported pixel formats for the writeback 
> > > > > engine
> > > > > - * @n_formats: Length of the formats array
> > > > > - * @possible_crtcs: possible crtcs for the internal writeback encoder
> > > > > - *
> > > > > - * This function creates the writeback-connector-specific properties 
> > > > > if they
> > > > > - * have not been already created, initializes the connector as
> > > > > - * type DRM_MODE_CONNECTOR_WRITEBACK, and correctly initializes the 
> > > > > property
> > > > > - * values. It will also create an internal encoder associated with 
> > > > > the
> > > > > - * drm_writeback_connector and set it to use the @enc_helper_funcs 
> > > > > vtable for
> > > > > - * the encoder helper.
> > > > > - *
> > > > > - * Drivers should always use this function instead of 
> > > > > drm_connector_init() to
> > > > > - * set up writeback connectors.
> > > > > - *
> > > > > - * Returns: 0 on success, or a negative error code
> > > > > - */
> > > > > -int drm_writeback_connector_init(struct drm_device *dev,
> > > > > -  struct drm_writeback_connector 
> > > > > *wb_connector,
> > > > > -  const struct drm_connector_funcs 
> > > > > *con_funcs,
> > > > > -  const struct drm_encoder_helper_funcs 
> > > > > *enc_helper_funcs,
> > > > > -  const u32 *formats, int n_formats, 
> > > > > uint32_t possible_crtcs)
> > > > > +static int drm_writeback_connector_setup(struct drm_device *dev,
> > > > > + struct drm_writeback_connector *wb_connector,
> > > > > + const struct drm_connector_funcs *con_funcs, const u32 
> > > > > *formats,
> > > > > + int n_formats)
> > > > >{
> > > > >   struct drm_property_blob *blob;
> > > > > - struct drm_connector *connector = &wb_connector->base;
> > > > >   struct drm_mode_config *config = &dev->mode_config;
> > > > > + struct drm_connector *connector = &wb_connector->base;
> > > > > +
> > > > 
> > > > Point of this reordering the statements is...?
> > > This diff can be avoided. There was no reason to reorder this. I will 
> > > remove
> > > this re-order.
> > > > 
> > > > >   int ret = create_writeback_properties(dev);
> > > > >   if (ret != 0)
> > > > > @@ -187,18 +165,10 @@ int drm_writeback_connector_init(struct 
> > > > > drm_device *dev,
> > > > >   blob = drm_property_create_blob(dev, n_formats * 
> > > > > sizeof(*formats),
> > > > >   formats);
> > > > > - if (IS_ERR(blob))
> > > > > - return PTR_ERR(blob);
> > > > > -
> > > > > - drm_encoder_helper_add(

Re: [PATCH 2/2] dma-buf/sync-file: fix warning about fence containers

2022-03-25 Thread Christian König

Am 25.03.22 um 11:13 schrieb Daniel Vetter:

On Fri, Mar 11, 2022 at 12:02:44PM +0100, Christian König wrote:

The dma_fence_chain containers can show up in sync_files as well resulting in
warnings that those can't be added to dma_fence_array containers when merging
multiple sync_files together.

Solve this by using the dma_fence_unwrap iterator to deep dive into the
contained fences and then add those flatten out into a dma_fence_array.

Signed-off-by: Christian König 

I have no idea why we try to keep fences sorted, but oh well it looks like
the merging is done correctly.


To be honest I don't fully know either.

Keeping the array sorted by context allows to merge it without adding 
duplicates, but adding duplicates is not an extra overhead to begin with 
because we always allocate memory for the worst case anyway.


Just keeping it around for now.


Reviewed-by: Daniel Vetter 


Thanks,
Christian.




---
  drivers/dma-buf/sync_file.c | 141 +++-
  1 file changed, 73 insertions(+), 68 deletions(-)

diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c
index 394e6e1e9686..b8dea4ec123b 100644
--- a/drivers/dma-buf/sync_file.c
+++ b/drivers/dma-buf/sync_file.c
@@ -5,6 +5,7 @@
   * Copyright (C) 2012 Google, Inc.
   */
  
+#include 

  #include 
  #include 
  #include 
@@ -172,20 +173,6 @@ static int sync_file_set_fence(struct sync_file *sync_file,
return 0;
  }
  
-static struct dma_fence **get_fences(struct sync_file *sync_file,

-int *num_fences)
-{
-   if (dma_fence_is_array(sync_file->fence)) {
-   struct dma_fence_array *array = 
to_dma_fence_array(sync_file->fence);
-
-   *num_fences = array->num_fences;
-   return array->fences;
-   }
-
-   *num_fences = 1;
-   return &sync_file->fence;
-}
-
  static void add_fence(struct dma_fence **fences,
  int *i, struct dma_fence *fence)
  {
@@ -210,86 +197,97 @@ static void add_fence(struct dma_fence **fences,
  static struct sync_file *sync_file_merge(const char *name, struct sync_file 
*a,
 struct sync_file *b)
  {
+   struct dma_fence *a_fence, *b_fence, **fences;
+   struct dma_fence_unwrap a_iter, b_iter;
+   unsigned int index, num_fences;
struct sync_file *sync_file;
-   struct dma_fence **fences = NULL, **nfences, **a_fences, **b_fences;
-   int i = 0, i_a, i_b, num_fences, a_num_fences, b_num_fences;
  
  	sync_file = sync_file_alloc();

if (!sync_file)
return NULL;
  
-	a_fences = get_fences(a, &a_num_fences);

-   b_fences = get_fences(b, &b_num_fences);
-   if (a_num_fences > INT_MAX - b_num_fences)
-   goto err;
+   num_fences = 0;
+   dma_fence_unwrap_for_each(a_fence, &a_iter, a->fence)
+   ++num_fences;
+   dma_fence_unwrap_for_each(b_fence, &b_iter, b->fence)
+   ++num_fences;
  
-	num_fences = a_num_fences + b_num_fences;

+   if (num_fences > INT_MAX)
+   goto err_free_sync_file;
  
  	fences = kcalloc(num_fences, sizeof(*fences), GFP_KERNEL);

if (!fences)
-   goto err;
+   goto err_free_sync_file;
  
  	/*

-* Assume sync_file a and b are both ordered and have no
-* duplicates with the same context.
+* We can't guarantee that fences in both a and b are ordered, but it is
+* still quite likely.
 *
-* If a sync_file can only be created with sync_file_merge
-* and sync_file_create, this is a reasonable assumption.
+* So attempt to order the fences as we pass over them and merge fences
+* with the same context.
 */
-   for (i_a = i_b = 0; i_a < a_num_fences && i_b < b_num_fences; ) {
-   struct dma_fence *pt_a = a_fences[i_a];
-   struct dma_fence *pt_b = b_fences[i_b];
  
-		if (pt_a->context < pt_b->context) {

-   add_fence(fences, &i, pt_a);
+   index = 0;
+   for (a_fence = dma_fence_unwrap_first(a->fence, &a_iter),
+b_fence = dma_fence_unwrap_first(b->fence, &b_iter);
+a_fence || b_fence; ) {
+
+   if (!b_fence) {
+   add_fence(fences, &index, a_fence);
+   a_fence = dma_fence_unwrap_next(&a_iter);
+
+   } else if (!a_fence) {
+   add_fence(fences, &index, b_fence);
+   b_fence = dma_fence_unwrap_next(&b_iter);
+
+   } else if (a_fence->context < b_fence->context) {
+   add_fence(fences, &index, a_fence);
+   a_fence = dma_fence_unwrap_next(&a_iter);
  
-			i_a++;

-   } else if (pt_a->context > pt_b->context) {
-   add_fence(fences, &i, pt_b);
+   } else if (b_fence->context < a_fence->context) {
+   add_fen

Re: [PATCH] dt-bindings: display: bridge: Drop requirement on input port for DSI devices

2022-03-25 Thread Tomi Valkeinen

Hi Maxime,

On 24/03/2022 16:23, Maxime Ripard wrote:

On Thu, Mar 24, 2022 at 03:43:42PM +0200, Laurent Pinchart wrote:

On Thu, Mar 24, 2022 at 09:18:19AM +0100, Maxime Ripard wrote:

On Wed, Mar 23, 2022 at 10:38:19PM +0200, Laurent Pinchart wrote:

Hi Maxime,

(CC'ing Sakari)

Thank you for the patch.

On Wed, Mar 23, 2022 at 04:48:23PM +0100, Maxime Ripard wrote:

MIPI-DSI devices, if they are controlled through the bus itself, have to
be described as a child node of the controller they are attached to.

Thus, there's no requirement on the controller having an OF-Graph output
port to model the data stream: it's assumed that it would go from the
parent to the child.

However, some bridges controlled through the DSI bus still require an
input OF-Graph port, thus requiring a controller with an OF-Graph output
port. This prevents those bridges from being used with the controllers
that do not have one without any particular reason to.

Let's drop that requirement.


I'm sure this won't come as a surprise, I'm very much opposed to this
change, for two reasons.

First, ports are part of the hardware, even if they're not connected. It
thus simplifies handling in drivers if they're always present.

Then, and that's the most important reason, I think it's a mistake not
to model the DSI data connection using OF graph unconditionally, even
when the DSI sink device is also controlled through the DSI bus (using
DCS) and is in that case a child of the DSI source device in the DT
hierarchy.


That's the way we do for any other device though. You never addressed
that comment, but it's very much the same that occurs for i2c or spi
controllers and their device. They all get their data from the parent
bus. I don't see you advocate for using OF-Graph for those devices.


Those are different, there's no data stream independent of the control
communications.


Fine, then you have Ethernet PHYs, or any MMIO device that does DMA.


Have those devices had the need for OF graphs? For display and capture 
we have a clear need. I don't think we should sometimes use OF graphs 
and sometimes not, but rather use them consistently at least in any new 
driver.



The device tree describes a control hierarchy between devices. OF graph
overlays on top of that a data transfer graph. The two are different
concepts, and the fact that DSI can sometimes be used as a control bus
doesn't change the concept. Using OF graph unconditionally to describe
the data connections for DSI leads to less variation in the device tree
structure, and thus less complexity in the implementation. We're
suffering from the fact we haven't made it a requirement in the first
place, which can't be fixed due to ABI breakage constraints, but let's
not acknowledge it as a good idea.


Honestly, it doesn't matter one bit.

We have a huge discrepancy here today, and only a couple of bridges have
that arbitrary restriction. The situation you don't want to acknowledge
is the de-facto standard, by the generic binding and by what all the
bridges and panels are implementing. Even panel-simple-dsi is doing it.
So it's very much there already.


It's here, and I think we should move away from it for new DSI sinks.
I'd like OF graph to be used consistently for new drivers. We can't
change existing DT bindings and drivers to drop support for the
non-OF-graph description due to ABI stability, but we can avoid
repeating the mistake going forward.


What I'm trying to address here is that some controllers that do
everything right can't be used because that restriction is completely
arbitrary and in opposition to the consensus. And they can't be used
*today*.

If we want to change that consensus, fine, but we should still have one.
Having some bridges enforcing custom rules for no reason is very much
unacceptable.

And changing that consensus won't happen overtime, we'll have to take
care of the backward compatibility, etc. So it won't fix the issue that
we can't use any bridge with any controller any time soon.


I don't think that's the issue at hand here. You can still use a
non-OF-graph DT event if the nodes for the two bridges affected by this
patch define a port@0. It can just be left unconnected.

I do agree it will cause some DT bindings for DCS-based DSI sinks to
have ports will others won't. If your concern is that all DT bindings
should be coherent, would you be OK with a patch that makes the sink
port mandatory in all DT bindings for DSI bridges and panels (and fixes
the mainline DT sources accordingly to make sure they validate) ? The
port would not be connected of course (at least when used with DSI
source drivers that don't use OF graph today). That would make DT
bindings coherent, and would be a first step towards using OF graph
everywhere.


I'm trying to fix a (recent) mistake/cargo-cult in new bindings. That
discussion is not going to be fairly controversial and I don't see how
that can be solved quickly. So, as a second step, why not. But this one
needs to come fi

Re: [PATCH] drm/i915/uapi: Document DRM_I915_QUERY_HWCONFIG_BLOB

2022-03-25 Thread Tvrtko Ursulin



On 25/03/2022 09:53, Daniel Vetter wrote:

On Fri, Mar 25, 2022 at 09:49:16AM +, Tvrtko Ursulin wrote:

From: Tvrtko Ursulin 

UAPI with absolutely no documentation should not have been added -
clarify blob format and content will be described externally.

Fixes: 78e1fb3112c0 ("drm/i915/uapi: Add query for hwconfig blob")
Signed-off-by: Tvrtko Ursulin 
Co-developed-by: Jordan Justen 
Cc: Jon Bloomfield 
Cc: Daniel Vetter 
Cc: John Harrison 
Cc: Jon Ewins 
Cc: Joonas Lahtinen 
Cc: Rodrigo Vivi 
---
  include/uapi/drm/i915_drm.h | 13 +
  1 file changed, 13 insertions(+)

diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 071ffd9d51f1..8d0719bee8fc 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -2683,6 +2683,9 @@ struct drm_i915_perf_oa_config {
   *
   * The behaviour is determined by the @query_id. Note that exactly what
   * @data_ptr is also depends on the specific @query_id.
+ *
+ * For specific queries see:
+ *  * `GuC HWCONFIG blob uAPI`_


I'd put this into the @query_id section, and then make it an item list
with the #define as the label, so that it becomes tidy and can neatly
iterate them all.

Anyway we can bikeshed this all more in a follow-up.

Reviewed-by: Daniel Vetter 


Thanks, yes I wanted to do the minimal thing to close the gap.

   */
  struct drm_i915_query_item {
/** @query_id: The id for this query */
@@ -3135,6 +3138,16 @@ struct drm_i915_query_memory_regions {
struct drm_i915_memory_region_info regions[];
  };
  
+/**

+ * DOC: GuC HWCONFIG blob uAPI
+ *
+ * The GuC produces a blob with information about the current device.
+ * i915 reads this blob from GuC and makes it available via this uAPI.
+ *
+ * The format and meading of the blob content are documented in the


Meading? I will fix that up while merging.

Regards,

Tvrtko


+ * Programmer's Reference Manual.
+ */
+
  /**
   * struct drm_i915_gem_create_ext - Existing gem_create behaviour, with added
   * extension support using struct i915_user_extension.
--
2.32.0





[PATCH v5 01/13] drm/msm/dsi: add support for dsc data

2022-03-25 Thread Vinod Koul
Display Stream Compression (DSC) parameters need to be calculated. Add
helpers and struct msm_display_dsc_config in msm_drv for this
msm_display_dsc_config uses drm_dsc_config for DSC parameters.

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 132 +
 drivers/gpu/drm/msm/msm_drv.h  |  15 
 2 files changed, 147 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 6b3ced4aaaf5..27553194f9fa 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -31,6 +31,8 @@
 
 #define DSI_RESET_TOGGLE_DELAY_MS 20
 
+static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc);
+
 static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
 {
u32 ver;
@@ -157,6 +159,7 @@ struct msm_dsi_host {
struct regmap *sfpb;
 
struct drm_display_mode *mode;
+   struct msm_display_dsc_config *dsc;
 
/* connected device info */
struct device_node *device_node;
@@ -1718,6 +1721,135 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host 
*msm_host,
return -EINVAL;
 }
 
+static u32 dsi_dsc_rc_buf_thresh[DSC_NUM_BUF_RANGES - 1] = {
+   0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62,
+   0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e
+};
+
+/* only 8bpc, 8bpp added */
+static char min_qp[DSC_NUM_BUF_RANGES] = {
+   0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13
+};
+
+static char max_qp[DSC_NUM_BUF_RANGES] = {
+   4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15
+};
+
+static char bpg_offset[DSC_NUM_BUF_RANGES] = {
+   2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12
+};
+
+static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc)
+{
+   int mux_words_size;
+   int groups_per_line, groups_total;
+   int min_rate_buffer_size;
+   int hrd_delay;
+   int pre_num_extra_mux_bits, num_extra_mux_bits;
+   int slice_bits;
+   int target_bpp_x16;
+   int data;
+   int final_value, final_scale;
+   int i;
+
+   dsc->drm->rc_model_size = 8192;
+   dsc->drm->first_line_bpg_offset = 12;
+   dsc->drm->rc_edge_factor = 6;
+   dsc->drm->rc_tgt_offset_high = 3;
+   dsc->drm->rc_tgt_offset_low = 3;
+   dsc->drm->simple_422 = 0;
+   dsc->drm->convert_rgb = 1;
+   dsc->drm->vbr_enable = 0;
+
+   /* handle only bpp = bpc = 8 */
+   for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++)
+   dsc->drm->rc_buf_thresh[i] = dsi_dsc_rc_buf_thresh[i];
+
+   for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
+   dsc->drm->rc_range_params[i].range_min_qp = min_qp[i];
+   dsc->drm->rc_range_params[i].range_max_qp = max_qp[i];
+   dsc->drm->rc_range_params[i].range_bpg_offset = bpg_offset[i];
+   }
+
+   dsc->drm->initial_offset = 6144; /* Not bpp 12 */
+   if (dsc->drm->bits_per_pixel != 8)
+   dsc->drm->initial_offset = 2048;/* bpp = 12 */
+
+   mux_words_size = 48;/* bpc == 8/10 */
+   if (dsc->drm->bits_per_component == 12)
+   mux_words_size = 64;
+
+   dsc->drm->initial_xmit_delay = 512;
+   dsc->drm->initial_scale_value = 32;
+   dsc->drm->first_line_bpg_offset = 12;
+   dsc->drm->line_buf_depth = dsc->drm->bits_per_component + 1;
+
+   /* bpc 8 */
+   dsc->drm->flatness_min_qp = 3;
+   dsc->drm->flatness_max_qp = 12;
+   dsc->det_thresh_flatness = 7 + 2 * (dsc->drm->bits_per_component - 8);
+   dsc->drm->rc_quant_incr_limit0 = 11;
+   dsc->drm->rc_quant_incr_limit1 = 11;
+   dsc->drm->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
+
+   /* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
+* params are calculated
+*/
+   dsc->slice_last_group_size = 3 - (dsc->drm->slice_width % 3);
+   groups_per_line = DIV_ROUND_UP(dsc->drm->slice_width, 3);
+   dsc->drm->slice_chunk_size = dsc->drm->slice_width * 
dsc->drm->bits_per_pixel / 8;
+   if ((dsc->drm->slice_width * dsc->drm->bits_per_pixel) % 8)
+   dsc->drm->slice_chunk_size++;
+
+   /* rbs-min */
+   min_rate_buffer_size =  dsc->drm->rc_model_size - 
dsc->drm->initial_offset +
+   dsc->drm->initial_xmit_delay * 
dsc->drm->bits_per_pixel +
+   groups_per_line * 
dsc->drm->first_line_bpg_offset;
+
+   hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, 
dsc->drm->bits_per_pixel);
+
+   dsc->drm->initial_dec_delay = hrd_delay - dsc->drm->initial_xmit_delay;
+
+   dsc->drm->initial_scale_value = 8 * dsc->drm->rc_model_size /
+  (dsc->drm->rc_model_size - 
dsc->drm->initial_offset);
+
+   slice_bits = 8 * dsc->drm->slice_chunk_size * dsc->drm->slice_height;
+
+   groups_total = groups_per_line * dsc->drm->slice_he

[PATCH v5 00/13] drm/msm: Add Display Stream Compression Support

2022-03-25 Thread Vinod Koul
Display Stream Compression (DSC) compresses the display stream in host which
is later decoded by panel. This series enables this for Qualcomm msm driver.
This was tested on Google Pixel3 phone which use LGE SW43408 panel.
 
The changes include DSC data and hardware block enabling for DPU1 then
support in encoder. We also add support in DSI and introduce required
topology changes.
 
In order for panel to set the DSC parameters we add dsc in drm_panel and
pass the dsc configuration from the panel driver

We still have dsc as a globabl entity. I think while doing DP + DSC we
should be able to update it, right now comprehending the requirements are
bit difficult.
 
Complete changes which enable this for Pixel3 along with panel driver (not
part of this series) and DT changes can be found at:
git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_v5
 
Comments welcome!

Changes since v4:
 - Use new apprach based on Abhinav suggestion for dsc with 3d-merge
 - Make common function for dsc timing caln and call that from video and cmd
   mode
 - update description for patch "Pass DSC params to drm_panel"
 - update couple of typos as pointed by Marijn
 - drop dpu_encoder_dsc_pclk_param_calc() as that was duplicating the caln
   done in dsi timing
 - Update copyright to 2022 to new files
 - Update Abhinav's email to new quic one

Changes since v3:
 - Merge changes from Dmitry to have dsc per encoder instance
 - add warning for dsc and mode3d enabled together
 - set dsc in dpu_encoder_phys_vid as well
 - remove dsc hardcoded mask
 - use devm_kzalloc for memory allocation for dsc

Changes since v2:
 - Fix comments by Dimitry except the dsc being global.
 - Move RM patch later for dependency on topology now
 - Add patch for mode valid callback for dsi_mgr
 - Add missing structure documentation patch
 - Fix errors in mode_3d changes
 - Rebase on v5.16-rc1 and test

Changes since v1:
 - Fix various issues spotted by kbuildbot
 - Rebase to v5.15-rc3
 - Remove unused fields and duplicate defines
 - Enable DSC blocks only when DSC is enabled
 - remove sdm845 feature mask, use 0
 - Check for DSC in hw_ctl

Changes since RFC:
 - Drop the DT binding patch as we derive the configuration from panel
 - Drop the drm api patch as we no longer need it (use pps drm api)
 - Fix comments raised by Dimitry
 - Add dsc parameters calculation from downstream

Dmitry Baryshkov (1):
  drm/msm/dpu: don't use merge_3d if DSC merge topology is used

Vinod Koul (12):
  drm/msm/dsi: add support for dsc data
  drm/msm/dsi: Pass DSC params to drm_panel
  drm/msm/disp/dpu1: Add support for DSC
  drm/msm/disp/dpu1: Add support for DSC in pingpong block
  drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog
  drm/msm/disp/dpu1: Add DSC support in hw_ctl
  drm/msm/disp/dpu1: Add support for DSC in encoder
  drm/msm: Add missing num_dspp field documentation
  drm/msm/disp/dpu1: Add support for DSC in topology
  drm/msm/disp/dpu1: Add DSC support in RM
  drm/msm/dsi: add mode valid callback for dsi_mgr
  drm/msm/dsi: Add support for DSC configuration

 drivers/gpu/drm/msm/Makefile  |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 155 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |   6 +
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  12 +-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c|  20 ++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|  13 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c|  11 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h|   2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 210 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h|  77 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   |  32 ++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   |  14 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |   2 +
 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 +
 drivers/gpu/drm/msm/dsi/dsi.c |   5 +
 drivers/gpu/drm/msm/dsi/dsi.h |   3 +
 drivers/gpu/drm/msm/dsi/dsi.xml.h |  10 +
 drivers/gpu/drm/msm/dsi/dsi_host.c| 274 +-
 drivers/gpu/drm/msm/dsi/dsi_manager.c |  12 +
 drivers/gpu/drm/msm/msm_drv.h |  26 ++
 include/drm/drm_panel.h   |   7 +
 24 files changed, 959 insertions(+), 4 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h

-- 
2.34.1



[PATCH v5 02/13] drm/msm/dsi: Pass DSC params to drm_panel

2022-03-25 Thread Vinod Koul
When DSC is enabled, we need to get the DSC parameters from the panel
driver, so add a dsc parameter in panel to fetch and pass DSC
configuration for DSI panels to DPU encoder, which will enable and
then configure DSC hardware blocks accordingly.

Signed-off-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 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(&msm_host->base);
+
+   if (panel && panel->dsc) {
+   struct msm_display_dsc_config *dsc = msm_host->dsc;
+
+   if (!dsc) {
+   dsc = devm_kzalloc(&msm_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 is_te_using_watchdog_timer;
+   struct msm_display_dsc_config *dsc;
 };
 
 /* Commit/Event th

[PATCH v5 04/13] drm/msm/disp/dpu1: Add support for DSC in pingpong block

2022-03-25 Thread Vinod Koul
In SDM845, DSC can be enabled by writing to pingpong block registers, so
add support for DSC in hw_pp

Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   | 32 +++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   | 14 
 2 files changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
index 55766c97c4c8..47c6ab6caf95 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
@@ -28,6 +28,9 @@
 #define PP_FBC_MODE 0x034
 #define PP_FBC_BUDGET_CTL   0x038
 #define PP_FBC_LOSSY_MODE   0x03C
+#define PP_DSC_MODE 0x0a0
+#define PP_DCE_DATA_IN_SWAP 0x0ac
+#define PP_DCE_DATA_OUT_SWAP0x0c8
 
 #define PP_DITHER_EN   0x000
 #define PP_DITHER_BITDEPTH 0x004
@@ -245,6 +248,32 @@ static u32 dpu_hw_pp_get_line_count(struct dpu_hw_pingpong 
*pp)
return line;
 }
 
+static int dpu_hw_pp_dsc_enable(struct dpu_hw_pingpong *pp)
+{
+   struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+   DPU_REG_WRITE(c, PP_DSC_MODE, 1);
+   return 0;
+}
+
+static void dpu_hw_pp_dsc_disable(struct dpu_hw_pingpong *pp)
+{
+   struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+   DPU_REG_WRITE(c, PP_DSC_MODE, 0);
+}
+
+static int dpu_hw_pp_setup_dsc(struct dpu_hw_pingpong *pp)
+{
+   struct dpu_hw_blk_reg_map *pp_c = &pp->hw;
+   int data;
+
+   data = DPU_REG_READ(pp_c, PP_DCE_DATA_OUT_SWAP);
+   data |= BIT(18); /* endian flip */
+   DPU_REG_WRITE(pp_c, PP_DCE_DATA_OUT_SWAP, data);
+   return 0;
+}
+
 static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
unsigned long features)
 {
@@ -256,6 +285,9 @@ static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
c->ops.get_autorefresh = dpu_hw_pp_get_autorefresh_config;
c->ops.poll_timeout_wr_ptr = dpu_hw_pp_poll_timeout_wr_ptr;
c->ops.get_line_count = dpu_hw_pp_get_line_count;
+   c->ops.setup_dsc = dpu_hw_pp_setup_dsc;
+   c->ops.enable_dsc = dpu_hw_pp_dsc_enable;
+   c->ops.disable_dsc = dpu_hw_pp_dsc_disable;
 
if (test_bit(DPU_PINGPONG_DITHER, &features))
c->ops.setup_dither = dpu_hw_pp_setup_dither;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
index 89d08a715c16..12758468d9ca 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
@@ -124,6 +124,20 @@ struct dpu_hw_pingpong_ops {
 */
void (*setup_dither)(struct dpu_hw_pingpong *pp,
struct dpu_hw_dither_cfg *cfg);
+   /**
+* Enable DSC
+*/
+   int (*enable_dsc)(struct dpu_hw_pingpong *pp);
+
+   /**
+* Disable DSC
+*/
+   void (*disable_dsc)(struct dpu_hw_pingpong *pp);
+
+   /**
+* Setup DSC
+*/
+   int (*setup_dsc)(struct dpu_hw_pingpong *pp);
 };
 
 struct dpu_hw_merge_3d;
-- 
2.34.1



[PATCH v5 03/13] drm/msm/disp/dpu1: Add support for DSC

2022-03-25 Thread Vinod Koul
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 
---
 drivers/gpu/drm/msm/Makefile  |   1 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|  13 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 210 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h|  77 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 ++
 5 files changed, 314 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 03ab55c37beb..7ec3c70c77ce 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -56,6 +56,7 @@ msm-y := \
disp/dpu1/dpu_formats.o \
disp/dpu1/dpu_hw_catalog.o \
disp/dpu1/dpu_hw_ctl.o \
+   disp/dpu1/dpu_hw_dsc.o \
disp/dpu1/dpu_hw_interrupts.o \
disp/dpu1/dpu_hw_intf.o \
disp/dpu1/dpu_hw_lm.o \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 31af04afda7d..5fc0888351c7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -556,6 +556,16 @@ struct dpu_merge_3d_cfg  {
const struct dpu_merge_3d_sub_blks *sblk;
 };
 
+/**
+ * struct dpu_dsc_cfg - information of DSC blocks
+ * @id enum identifying this block
+ * @base   register offset of this block
+ * @features   bit mask identifying sub-blocks/features
+ */
+struct dpu_dsc_cfg {
+   DPU_HW_BLK_INFO;
+};
+
 /**
  * struct dpu_intf_cfg - information of timing engine blocks
  * @id enum identifying this block
@@ -752,6 +762,9 @@ struct dpu_mdss_cfg {
u32 merge_3d_count;
const struct dpu_merge_3d_cfg *merge_3d;
 
+   u32 dsc_count;
+   struct dpu_dsc_cfg *dsc;
+
u32 intf_count;
const struct dpu_intf_cfg *intf;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
new file mode 100644
index ..ff1d74e4aa2c
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020-2022, Linaro Limited
+ */
+
+#include "dpu_kms.h"
+#include "dpu_hw_catalog.h"
+#include "dpu_hwio.h"
+#include "dpu_hw_mdss.h"
+#include "dpu_hw_dsc.h"
+
+#define DSC_COMMON_MODE0x000
+#define DSC_ENC 0X004
+#define DSC_PICTURE 0x008
+#define DSC_SLICE   0x00C
+#define DSC_CHUNK_SIZE  0x010
+#define DSC_DELAY   0x014
+#define DSC_SCALE_INITIAL   0x018
+#define DSC_SCALE_DEC_INTERVAL  0x01C
+#define DSC_SCALE_INC_INTERVAL  0x020
+#define DSC_FIRST_LINE_BPG_OFFSET   0x024
+#define DSC_BPG_OFFSET  0x028
+#define DSC_DSC_OFFSET  0x02C
+#define DSC_FLATNESS0x030
+#define DSC_RC_MODEL_SIZE   0x034
+#define DSC_RC  0x038
+#define DSC_RC_BUF_THRESH   0x03C
+#define DSC_RANGE_MIN_QP0x074
+#define DSC_RANGE_MAX_QP0x0B0
+#define DSC_RANGE_BPG_OFFSET0x0EC
+
+static void dpu_hw_dsc_disable(struct dpu_hw_dsc *dsc)
+{
+   struct dpu_hw_blk_reg_map *c = &dsc->hw;
+
+   DPU_REG_WRITE(c, DSC_COMMON_MODE, 0);
+}
+
+static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
+ struct msm_display_dsc_config *dsc, u32 mode)
+{
+   struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
+   u32 data, lsb, bpp;
+   u32 initial_lines = dsc->initial_lines;
+   bool is_cmd_mode = !(mode & DSC_MODE_VIDEO);
+
+   DPU_REG_WRITE(c, DSC_COMMON_MODE, mode);
+
+   if (is_cmd_mode)
+   initial_lines += 1;
+
+   data = (initial_lines << 20);
+   data |= ((dsc->slice_last_group_size - 1) << 18);
+   /* bpp is 6.4 format, 4 LSBs bits are for fractional part */
+   data |= dsc->drm->bits_per_pixel << 12;
+   lsb = dsc->drm->bits_per_pixel % 4;
+   bpp = dsc->drm->bits_per_pixel / 4;
+   bpp *= 4;
+   bpp <<= 4;
+   bpp |= lsb;
+
+   data |= bpp << 8;
+   data |= (dsc->drm->block_pred_enable << 7);
+   data |= (dsc->drm->line_buf_depth << 3);
+   data |= (dsc->drm->simple_422 << 2);
+   data |= (dsc->drm->convert_rgb << 1);
+   data |= dsc->drm->bits_per_component;
+
+   DPU_REG_WRITE(c, DSC_ENC, data);
+
+   data = dsc->drm->pic_width << 16;
+   data |= dsc->drm->pic_height;
+   DPU_REG_WRITE(c, DSC_PICTURE, data);
+
+   data = dsc->drm->slice_width << 16;
+   data |= dsc->drm->slice_height;
+   DPU_REG_WRITE(c, DSC_SLICE, data);
+
+   data = ds

[PATCH v5 05/13] drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog

2022-03-25 Thread Vinod Koul
This adds SDM845 DSC blocks into hw_catalog

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 20 +++
 1 file changed, 20 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..9c09cf318dfb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -821,6 +821,24 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = {
PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, -1, -1),
PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, -1, -1),
 };
+
+/*
+ * DSC sub blocks config
+ */
+#define DSC_BLK(_name, _id, _base) \
+   {\
+   .name = _name, .id = _id, \
+   .base = _base, .len = 0x140, \
+   .features = 0, \
+   }
+
+static struct dpu_dsc_cfg sdm845_dsc[] = {
+   DSC_BLK("dsc_0", DSC_0, 0x8),
+   DSC_BLK("dsc_1", DSC_1, 0x80400),
+   DSC_BLK("dsc_2", DSC_2, 0x80800),
+   DSC_BLK("dsc_3", DSC_3, 0x80c00),
+};
+
 /*
  * INTF sub blocks config
  */
@@ -1124,6 +1142,8 @@ static void sdm845_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
.mixer = sdm845_lm,
.pingpong_count = ARRAY_SIZE(sdm845_pp),
.pingpong = sdm845_pp,
+   .dsc_count = ARRAY_SIZE(sdm845_dsc),
+   .dsc = sdm845_dsc,
.intf_count = ARRAY_SIZE(sdm845_intf),
.intf = sdm845_intf,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
-- 
2.34.1



[PATCH v5 07/13] drm/msm/disp/dpu1: Add support for DSC in encoder

2022-03-25 Thread Vinod Koul
We need to configure the encoder for DSC configuration and calculate DSC
parameters for the given timing so this patch adds that support by
adding dpu_encoder_prep_dsc() which is invoked when DSC is enabled.

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 126 +-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   8 ++
 2 files changed, 133 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 1e648db439f9..2219dbfa5ee7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -21,6 +21,7 @@
 #include "dpu_hw_intf.h"
 #include "dpu_hw_ctl.h"
 #include "dpu_hw_dspp.h"
+#include "dpu_hw_dsc.h"
 #include "dpu_formats.h"
 #include "dpu_encoder_phys.h"
 #include "dpu_crtc.h"
@@ -136,6 +137,8 @@ enum dpu_enc_rc_states {
  * @cur_slave: As above but for the slave encoder.
  * @hw_pp: Handle to the pingpong blocks used for the display. No.
  * pingpong blocks can be different than num_phys_encs.
+ * @hw_dsc:Handle to the DSC blocks used for the display.
+ * @dsc_mask:  Bitmask of used DSC blocks.
  * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
  * for partial update right-only cases, such as pingpong
  * split where virtual pingpong does not generate IRQs
@@ -169,6 +172,7 @@ enum dpu_enc_rc_states {
  * @topology:   topology of the display
  * @idle_timeout:  idle timeout duration in milliseconds
  * @dp:msm_dp pointer, for DP encoders
+ * @dsc:   msm_display_dsc_config pointer, for DSC-enabled 
encoders
  */
 struct dpu_encoder_virt {
struct drm_encoder base;
@@ -182,6 +186,9 @@ struct dpu_encoder_virt {
struct dpu_encoder_phys *cur_master;
struct dpu_encoder_phys *cur_slave;
struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
+   struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
+
+   unsigned int dsc_mask;
 
bool intfs_swapped;
 
@@ -209,6 +216,9 @@ struct dpu_encoder_virt {
u32 idle_timeout;
 
struct msm_dp *dp;
+
+   /* DSC configuration */
+   struct msm_display_dsc_config *dsc;
 };
 
 #define to_dpu_encoder_virt(x) container_of(x, struct dpu_encoder_virt, base)
@@ -972,7 +982,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
-   int num_lm, num_ctl, num_pp;
+   struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
+   int num_lm, num_ctl, num_pp, num_dsc;
+   unsigned int dsc_mask = 0;
int i, j;
 
if (!drm_enc) {
@@ -1027,6 +1039,18 @@ 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;
 
+   if (dpu_enc->dsc) {
+   num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, 
global_state,
+   drm_enc->base.id, 
DPU_HW_BLK_DSC,
+   hw_dsc, 
ARRAY_SIZE(hw_dsc));
+   for (i = 0; i < num_dsc; i++) {
+   dpu_enc->hw_dsc[i] = to_dpu_hw_dsc(hw_dsc[i]);
+   dsc_mask |= BIT(dpu_enc->hw_dsc[i]->idx - DSC_0);
+   }
+   }
+
+   dpu_enc->dsc_mask = dsc_mask;
+
cstate = to_dpu_crtc_state(drm_crtc->state);
 
for (i = 0; i < num_lm; i++) {
@@ -1739,6 +1763,93 @@ static void dpu_encoder_vsync_event_work_handler(struct 
kthread_work *work)
nsecs_to_jiffies(ktime_to_ns(wakeup_time)));
 }
 
+static void
+dpu_encoder_dsc_initial_line_calc(struct msm_display_dsc_config *dsc,
+ u32 enc_ip_width)
+{
+   int ssm_delay, total_pixels, soft_slice_per_enc;
+
+   soft_slice_per_enc = enc_ip_width / dsc->drm->slice_width;
+
+   /*
+* minimum number of initial line pixels is a sum of:
+* 1. sub-stream multiplexer delay (83 groups for 8bpc,
+*91 for 10 bpc) * 3
+* 2. for two soft slice cases, add extra sub-stream multiplexer * 3
+* 3. the initial xmit delay
+* 4. total pipeline delay through the "lock step" of encoder (47)
+* 5. 6 additional pixels as the output of the rate buffer is
+*48 bits wide
+*/
+   ssm_delay = ((dsc->drm->bits_per_component < 10) ? 84 : 92);
+   total_pixels = ssm_delay * 3 + dsc->drm->initial_xmit_delay + 47;
+   if (soft_slice_per_enc > 1)
+   total_pi

[PATCH v5 08/13] drm/msm/dpu: don't use merge_3d if DSC merge topology is used

2022-03-25 Thread Vinod Koul
From: Dmitry Baryshkov 

DPU supports different topologies for the case when multiple INTFs are
being driven by the single phys_enc. The driver defaults to using 3DMux
in such cases. Don't use it if DSC merge is used instead.

Suggested-by: Abhinav Kumar 
Signed-off-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c  | 16 
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h  |  6 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h |  4 +++-
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 2219dbfa5ee7..a672c91dbb8b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -534,6 +534,22 @@ void dpu_encoder_helper_split_config(
}
 }
 
+bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
+{
+   struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
+   int i, intf_count = 0, num_dsc = 0;
+
+   for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
+   if (dpu_enc->phys_encs[i])
+   intf_count++;
+
+   /* See dpu_encoder_get_topology, we only support 2:2:1 topology */
+   if (dpu_enc->dsc)
+   num_dsc = 2;
+
+   return (num_dsc > 0) && (num_dsc > intf_count);
+}
+
 static struct msm_display_topology dpu_encoder_get_topology(
struct dpu_encoder_virt *dpu_enc,
struct dpu_kms *dpu_kms,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index e241914a9677..76fd48c0b17c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -168,4 +168,10 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc);
  */
 int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
 
+/**
+ * dpu_encoder_use_dsc_merge - returns true if the encoder uses DSC merge 
topology.
+ * @drm_enc:Pointer to previously created drm encoder structure
+ */
+bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc);
+
 #endif /* __DPU_ENCODER_H__ */
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 7b90d644a41b..a19140590eaa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -325,8 +325,10 @@ static inline enum dpu_3d_blend_mode 
dpu_encoder_helper_get_3d_blend_mode(
 
dpu_cstate = to_dpu_crtc_state(phys_enc->parent->crtc->state);
 
+   /* Use merge_3d unless DSC MERGE topology is used */
if (phys_enc->split_role == ENC_ROLE_SOLO &&
-   dpu_cstate->num_mixers == CRTC_DUAL_MIXERS)
+   dpu_cstate->num_mixers == CRTC_DUAL_MIXERS &&
+   !dpu_encoder_use_dsc_merge(phys_enc->parent))
return BLEND_3D_H_ROW_INT;
 
return BLEND_3D_NONE;
-- 
2.34.1



[PATCH v5 06/13] drm/msm/disp/dpu1: Add DSC support in hw_ctl

2022-03-25 Thread Vinod Koul
Later gens of hardware have DSC bits moved to hw_ctl, so configure these
bits so that DSC would work there as well

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 11 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h |  2 ++
 2 files changed, 12 insertions(+), 1 deletion(-)

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..cba94aa9fdcc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -25,6 +25,8 @@
 #define   CTL_MERGE_3D_ACTIVE   0x0E4
 #define   CTL_INTF_ACTIVE   0x0F4
 #define   CTL_MERGE_3D_FLUSH0x100
+#define   CTL_DSC_ACTIVE0x0E8
+#define   CTL_DSC_FLUSH0x104
 #define   CTL_INTF_FLUSH0x110
 #define   CTL_INTF_MASTER   0x134
 #define   CTL_FETCH_PIPE_ACTIVE 0x0FC
@@ -34,6 +36,7 @@
 
 #define DPU_REG_RESET_TIMEOUT_US2000
 #define  MERGE_3D_IDX   23
+#define  DSC_IDX22
 #define  INTF_IDX   31
 #define CTL_INVALID_BIT 0x
 #define CTL_DEFAULT_GROUP_ID   0xf
@@ -121,7 +124,6 @@ static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl 
*ctx)
 
 static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 {
-
if (ctx->pending_flush_mask & BIT(MERGE_3D_IDX))
DPU_REG_WRITE(&ctx->hw, CTL_MERGE_3D_FLUSH,
ctx->pending_merge_3d_flush_mask);
@@ -506,6 +508,9 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
if ((test_bit(DPU_CTL_VM_CFG, &ctx->caps->features)))
mode_sel = CTL_DEFAULT_GROUP_ID  << 28;
 
+   if (cfg->dsc)
+   DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, cfg->dsc);
+
if (cfg->intf_mode_sel == DPU_CTL_MODE_SEL_CMD)
mode_sel |= BIT(17);
 
@@ -517,6 +522,10 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
if (cfg->merge_3d)
DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,
  BIT(cfg->merge_3d - MERGE_3D_0));
+   if (cfg->dsc) {
+   DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, DSC_IDX);
+   DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc);
+   }
 }
 
 static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
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..75db89f66abd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -40,6 +40,7 @@ struct dpu_hw_stage_cfg {
  * @merge_3d:  3d merge block used
  * @intf_mode_sel: Interface mode, cmd / vid
  * @stream_sel:Stream selection for multi-stream interfaces
+ * @dsc:   DSC BIT masks used
  */
 struct dpu_hw_intf_cfg {
enum dpu_intf intf;
@@ -47,6 +48,7 @@ struct dpu_hw_intf_cfg {
enum dpu_merge_3d merge_3d;
enum dpu_ctl_mode_sel intf_mode_sel;
int stream_sel;
+   unsigned int dsc;
 };
 
 /**
-- 
2.34.1



[PATCH v5 10/13] drm/msm/disp/dpu1: Add support for DSC in topology

2022-03-25 Thread Vinod Koul
For DSC to work we typically need a 2,2,1 configuration. This should
suffice for resolutions up to 4k. For more resolutions like 8k this won't
work.

Also, it is better to use 2 LMs and DSC instances as half width results
in lesser power consumption as compared to single LM, DSC at full width.

The panel has been tested only with 2,2,1 configuration, so for
now we blindly create 2,2,1 topology when DSC is enabled

Co-developed-by: Abhinav Kumar 
Signed-off-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 13 +
 drivers/gpu/drm/msm/msm_drv.h   |  2 ++
 2 files changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index a672c91dbb8b..7dff39c20dab 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -590,8 +590,21 @@ static struct msm_display_topology 
dpu_encoder_get_topology(
topology.num_enc = 0;
topology.num_intf = intf_count;
 
+   if (dpu_enc->dsc) {
+   /* In case of Display Stream Compression (DSC), we would use
+* 2 encoders, 2 layer mixers and 1 interface
+* this is power optimal and can drive up to (including) 4k
+* screens
+*/
+   topology.num_enc = 2;
+   topology.num_dsc = 2;
+   topology.num_intf = 1;
+   topology.num_lm = 2;
+   }
+
return topology;
 }
+
 static int dpu_encoder_virt_atomic_check(
struct drm_encoder *drm_enc,
struct drm_crtc_state *crtc_state,
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 6425a42e997c..994d895d1a47 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -103,12 +103,14 @@ enum msm_event_wait {
  * @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
+ * @num_dsc:  number of Display Stream Compression (DSC) blocks used
  */
 struct msm_display_topology {
u32 num_lm;
u32 num_enc;
u32 num_intf;
u32 num_dspp;
+   u32 num_dsc;
 };
 
 /**
-- 
2.34.1



[PATCH v5 11/13] drm/msm/disp/dpu1: Add DSC support in RM

2022-03-25 Thread Vinod Koul
This add the bits in RM to enable the DSC blocks

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 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] = &hw->base;
}
 
+   for (i = 0; i < cat->dsc_count; i++) {
+   struct dpu_hw_dsc *hw;
+   const struct dpu_dsc_cfg *dsc = &cat->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] = &hw->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, &reqs->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];
struct dpu_hw_blk *dspp_blks[DSPP_MAX - D

[PATCH v5 12/13] drm/msm/dsi: add mode valid callback for dsi_mgr

2022-03-25 Thread Vinod Koul
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 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 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 */
-- 
2.34.1



[PATCH v5 09/13] drm/msm: Add missing num_dspp field documentation

2022-03-25 Thread Vinod Koul
Somehow documentation for num_dspp was missed, so add that

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 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;
-- 
2.34.1



[PATCH v5 13/13] drm/msm/dsi: Add support for DSC configuration

2022-03-25 Thread Vinod Koul
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 | 94 +-
 2 files changed, 103 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_CTRL0x029c
+
+#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL2   0x02a0
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL  0x02a4
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2 0x02a8
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL3 0x02ac
+
 #endif /* DSI_XML */
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 438c80750682..0f33e678103f 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -908,6 +908,61 @@ 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 void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool 
is_cmd_mode, u32 hdisplay)
+{
+   struct msm_display_dsc_config *dsc = msm_host->dsc;
+   u32 reg, intf_width, reg_ctrl, reg_ctrl2;
+   u32 slice_per_intf, total_bytes_per_intf;
+
+   /* first calculate dsc parameters and then program
+* compress mode registers
+*/
+   intf_width = hdisplay;
+   slice_per_intf = DIV_ROUND_UP(intf_width, dsc->drm->slice_width);
+
+   /* If slice_per_pkt is greater than slice_per_intf
+* then default to 1. This can happen during partial
+* update.
+*/
+   if (slice_per_intf > dsc->drm->slice_count)
+   dsc->drm->slice_count = 1;
+
+   slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->drm->slice_width);
+   dsc->bytes_in_slice = DIV_ROUND_UP(dsc->drm->slice_width *
+  dsc->drm->bits_per_pixel, 8);
+
+   dsc->drm->slice_chunk_size = dsc->bytes_in_slice;
+
+   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;
+
+   if (is_cmd_mode) /* packet data type */
+   reg = MIPI_DSI_DCS_LONG_WRITE << 8;
+   else
+   reg = MIPI_DSI_COMPRESSED_PIXEL_STREAM << 8;
+
+   reg |= (dsc->pkt_per_line >> 1) << 6;
+   reg |= dsc->eol_byte_num << 4;
+   reg |= 1;
+
+   if (is_cmd_mode) {
+   reg_ctrl = dsi_read(msm_host, 
REG_DSI_COMMAND_COMPRESSION_MODE_CTRL);
+   reg_ctrl2 = dsi_read(msm_host, 
REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2);
+
+   reg_ctrl |= reg;
+   reg_ctrl2 |= dsc->bytes_in_slice;
+
+   dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL, reg);
+   dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2, 
reg_ctrl2);
+   } else {
+   dsi_write(msm_host, REG_DSI_VIDEO_COMPRESSION_MODE_CTRL, reg);
+   }
+}
+
 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 +995,38 @@ 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 */
+   if (!dsc || !mode->hdisplay || !mode->vdisplay) {
+   pr_err("DSI: invalid input: pic_width: %d pic_height: 
%d\n",
+  mode->hdisplay, mode->vdisplay);
+   return;
+   }
+
+   dsc->drm->pic_width = mode->hdisplay;
+   dsc->drm->pic_height = mode->vdisplay;
+   DBG("Mode %dx%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
+* 

Re: [RFC] drm/i915: Split out intel_vtd_active and run_as_guest to own header

2022-03-25 Thread Jani Nikula
On Fri, 25 Mar 2022, Tvrtko Ursulin  wrote:
> On 24/03/2022 18:57, Jani Nikula wrote:
>> On Thu, 24 Mar 2022, Tvrtko Ursulin  wrote:
>>> On 24/03/2022 11:57, Jani Nikula wrote:
 On Thu, 24 Mar 2022, Tvrtko Ursulin  wrote:
> On 24/03/2022 09:31, Jani Nikula wrote:
>> On Tue, 22 Mar 2022, Tvrtko Ursulin  
>> wrote:
>>> From: Tvrtko Ursulin 
>>>
>>> ...
>>>
>>> Signed-off-by: Tvrtko Ursulin 
>>> Cc: Jani Nikula 
>>> Cc: Lucas De Marchi 
>>> ---
>>> Typed up how I see it - bash away.
>>
>> So is intel_vtd_active() so performance critical that it needs to be
>> inline?
>>
>> We're passing struct drm_i915_private * everywhere we can, and it just
>> feels silly to use struct drm_device * to avoid the include.
>>
>> Static inlines considered harmful. :p
>
> Same as it is ;), and gee, who was it that he said he was just trying to
> declutter i915_drv.h.. ;p

 Not at the cost of clarity elsewhere!
>>>
>>> To be clear now you oppose intel_vtd_active taking struct device? I
>>> thought you expressed general agreement when I presented the idea in the
>>> previous thread.
>>>
>>> I don't mind hugely to go either way, but I also don't see how taking
>>> struct device makes anything unclear. (I only think
>>> intel_vtd_run_as_guest is really wrong in this story but that's old news.)
>>>
>>> And if I make it take i915 then I would want to name it i915_vtd_active
>>> as well. But then you wouldn't like that.
>>>
>>> Should we just stuff all this into i915_utils for now, as I think Lucas
>>> suggested? Static inline or not, I don't care.
>> 
>> Just general grumpiness.
>> 
>> Acked-by: Jani Nikula 
>
> No worries. Ack is for this version or with i915_ prefixes in 
> i915_utils.h/c?

Both. Either. ;)

>
> Regards,
>
> Tvrtko

-- 
Jani Nikula, Intel Open Source Graphics Center


[PATCH v4 0/6] drm/msm: rework MDSS drivers

2022-03-25 Thread Dmitry Baryshkov
These patches coninue work started by AngeloGioacchino Del Regno in the
previous cycle by further decoupling and dissecting MDSS and MDP drivers
probe/binding paths.

This removes code duplication between MDP5 and DPU1 MDSS drivers, by
merging them and moving to the top level.

Changes since v4:
 - Fixed the issue with MODULE_DEVICE_TABLE reported by robot
 - Fixed the comments accoring to suggestions of Stephen
 - Removed extra goto (Stephen's suggestion)
 - Break long kms->dev->dev->parent chains into cleaner dpu_dev/mdp_dev
   and mdss_dev to document device tree bindings. Add related comments.
   (Stephen's suggestion)

Changes since v3:
 - Rebased on top of current msm/msm-next
 - Fixed issue with enabling/disabling MDP4/MDP5 vs DSI driver (per
   Stephen's suggestion)
 - Reworked mdss_probe to remove extra platform_set_drvdata calls (per
   Stephen's suggestion)
 - Fixed a typo in the Kconfig (noted by Rob)
 - Added a patch to move component mastership from mdss to mdp5/dpu1
   devices

Changes since v2:
 - Rebased on top of current msm/msm-next(-staging)
 - Allow disabling MDP4/MDP5/DPU/HDMI components (like we do for DP and
   DSI)
 - Made mdp5_mdss_parse_clock() static
 - Changed mdp5 to is_mdp5 argument in several functions
 - Dropped boolean device data from the mdss driver
 - Reworked error handling in msm_pdev_probe()
 - Removed unused header inclusion
 - Dropped __init/__exit from function prototypes

Changes since v1:
 - Rebased on top of [2] and [1]

[1] https://patchwork.freedesktop.org/series/99066/
[2] https://patchwork.freedesktop.org/series/98521/


Dmitry Baryshkov (6):
  drm/msm: unify MDSS drivers
  drm/msm: remove extra indirection for msm_mdss
  drm/msm: split the main platform driver
  drm/msm: stop using device's match data pointer
  drm/msm: allow compile time selection of driver components
  drm/msm: make mdp5/dpu devices master components

 drivers/gpu/drm/msm/Kconfig   |  50 ++-
 drivers/gpu/drm/msm/Makefile  |  25 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |  86 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c  | 260 
 .../gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c  |   3 +
 drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c  |  54 ++-
 .../gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c  |   3 +
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c  |  57 ++-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c | 252 
 drivers/gpu/drm/msm/msm_drv.c | 261 +++-
 drivers/gpu/drm/msm/msm_drv.h |  61 ++-
 drivers/gpu/drm/msm/msm_kms.h |  21 -
 drivers/gpu/drm/msm/msm_mdss.c| 375 ++
 13 files changed, 652 insertions(+), 856 deletions(-)
 delete mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
 delete mode 100644 drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c
 create mode 100644 drivers/gpu/drm/msm/msm_mdss.c

-- 
2.35.1



[PATCH v4 3/6] drm/msm: split the main platform driver

2022-03-25 Thread Dmitry Baryshkov
Currently the msm platform driver is a multiplex handling several cases:
- headless GPU-only driver,
- MDP4 with flat device nodes,
- MDP5/DPU MDSS with all the nodes being children of MDSS node.

This results in not-so-perfect code, checking the hardware version
(MDP4/MDP5/DPU) in several places, checking for mdss even when it can
not exist, etc. Split the code into three handling subdrivers (mdp4,
mdss and headless msm).

Reviewed-by: Abhinav Kumar 
Reported-by: kernel test robot 
Reviewed-by: Stephen Boyd 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c |  56 ++
 drivers/gpu/drm/msm/msm_drv.c| 228 ---
 drivers/gpu/drm/msm/msm_drv.h|  27 ++-
 drivers/gpu/drm/msm/msm_kms.h|   7 -
 drivers/gpu/drm/msm/msm_mdss.c   | 175 -
 5 files changed, 288 insertions(+), 205 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c 
b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
index 3cf476c55158..5dc839184aef 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
@@ -569,3 +569,59 @@ static struct mdp4_platform_config *mdp4_get_config(struct 
platform_device *dev)
 
return &config;
 }
+
+static const struct dev_pm_ops mdp4_pm_ops = {
+   .prepare = msm_pm_prepare,
+   .complete = msm_pm_complete,
+};
+
+static int mdp4_probe(struct platform_device *pdev)
+{
+   struct msm_drm_private *priv;
+
+   priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+   if (!priv)
+   return -ENOMEM;
+
+   platform_set_drvdata(pdev, priv);
+
+   /*
+* on MDP4 based platforms, the MDP platform device is the component
+* that adds other display interface components to itself.
+*/
+   return msm_drv_probe(&pdev->dev, &pdev->dev);
+}
+
+static int mdp4_remove(struct platform_device *pdev)
+{
+   component_master_del(&pdev->dev, &msm_drm_ops);
+
+   return 0;
+}
+
+static const struct of_device_id mdp4_dt_match[] = {
+   { .compatible = "qcom,mdp4", .data = (void *)KMS_MDP4 },
+   { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mdp4_dt_match);
+
+static struct platform_driver mdp4_platform_driver = {
+   .probe  = mdp4_probe,
+   .remove = mdp4_remove,
+   .shutdown   = msm_drv_shutdown,
+   .driver = {
+   .name   = "mdp4",
+   .of_match_table = mdp4_dt_match,
+   .pm = &mdp4_pm_ops,
+   },
+};
+
+void __init msm_mdp4_register(void)
+{
+   platform_driver_register(&mdp4_platform_driver);
+}
+
+void __exit msm_mdp4_unregister(void)
+{
+   platform_driver_unregister(&mdp4_platform_driver);
+}
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index d3cce39c13bf..16d8aa225405 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -256,10 +256,6 @@ static int msm_drm_uninit(struct device *dev)
return 0;
 }
 
-#define KMS_MDP4 4
-#define KMS_MDP5 5
-#define KMS_DPU  3
-
 static int get_mdp_ver(struct platform_device *pdev)
 {
struct device *dev = &pdev->dev;
@@ -970,50 +966,7 @@ static const struct drm_driver msm_driver = {
.patchlevel = MSM_VERSION_PATCHLEVEL,
 };
 
-static int __maybe_unused msm_runtime_suspend(struct device *dev)
-{
-   struct msm_drm_private *priv = dev_get_drvdata(dev);
-   struct msm_mdss *mdss = priv->mdss;
-
-   DBG("");
-
-   if (mdss)
-   return msm_mdss_disable(mdss);
-
-   return 0;
-}
-
-static int __maybe_unused msm_runtime_resume(struct device *dev)
-{
-   struct msm_drm_private *priv = dev_get_drvdata(dev);
-   struct msm_mdss *mdss = priv->mdss;
-
-   DBG("");
-
-   if (mdss)
-   return msm_mdss_enable(mdss);
-
-   return 0;
-}
-
-static int __maybe_unused msm_pm_suspend(struct device *dev)
-{
-
-   if (pm_runtime_suspended(dev))
-   return 0;
-
-   return msm_runtime_suspend(dev);
-}
-
-static int __maybe_unused msm_pm_resume(struct device *dev)
-{
-   if (pm_runtime_suspended(dev))
-   return 0;
-
-   return msm_runtime_resume(dev);
-}
-
-static int __maybe_unused msm_pm_prepare(struct device *dev)
+int msm_pm_prepare(struct device *dev)
 {
struct msm_drm_private *priv = dev_get_drvdata(dev);
struct drm_device *ddev = priv ? priv->dev : NULL;
@@ -1024,7 +977,7 @@ static int __maybe_unused msm_pm_prepare(struct device 
*dev)
return drm_mode_config_helper_suspend(ddev);
 }
 
-static void __maybe_unused msm_pm_complete(struct device *dev)
+void msm_pm_complete(struct device *dev)
 {
struct msm_drm_private *priv = dev_get_drvdata(dev);
struct drm_device *ddev = priv ? priv->dev : NULL;
@@ -1036,8 +989,6 @@ static void __maybe_unused msm_pm_complete(struct device 
*dev)
 }
 
 static const struct dev_pm_ops msm_pm_ops = {
-   SET_SYSTEM_SLEEP_PM_OP

[PATCH v4 1/6] drm/msm: unify MDSS drivers

2022-03-25 Thread Dmitry Baryshkov
MDP5 and DPU1 both provide the driver handling the MDSS region, which
handles the irq domain and (incase of DPU1) adds some init for the UBWC
controller. Unify those two pieces of code into a common driver.

Reviewed-by: Abhinav Kumar 
Reviewed-by: Stephen Boyd 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/Makefile  |   3 +-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c | 252 --
 drivers/gpu/drm/msm/msm_drv.c |   4 +-
 drivers/gpu/drm/msm/msm_kms.h |   3 +-
 .../msm/{disp/dpu1/dpu_mdss.c => msm_mdss.c}  | 145 +-
 5 files changed, 83 insertions(+), 324 deletions(-)
 delete mode 100644 drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c
 rename drivers/gpu/drm/msm/{disp/dpu1/dpu_mdss.c => msm_mdss.c} (63%)

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index e9cc7d8ac301..e76927b42033 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -42,7 +42,6 @@ msm-y := \
disp/mdp5/mdp5_crtc.o \
disp/mdp5/mdp5_encoder.o \
disp/mdp5/mdp5_irq.o \
-   disp/mdp5/mdp5_mdss.o \
disp/mdp5/mdp5_kms.o \
disp/mdp5/mdp5_pipe.o \
disp/mdp5/mdp5_mixer.o \
@@ -67,7 +66,6 @@ msm-y := \
disp/dpu1/dpu_hw_util.o \
disp/dpu1/dpu_hw_vbif.o \
disp/dpu1/dpu_kms.o \
-   disp/dpu1/dpu_mdss.o \
disp/dpu1/dpu_plane.o \
disp/dpu1/dpu_rm.o \
disp/dpu1/dpu_vbif.o \
@@ -88,6 +86,7 @@ msm-y := \
msm_gpu_devfreq.o \
msm_io_utils.o \
msm_iommu.o \
+   msm_mdss.o \
msm_perf.o \
msm_rd.o \
msm_ringbuffer.o \
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c
deleted file mode 100644
index 049c6784a531..
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c
+++ /dev/null
@@ -1,252 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
- */
-
-#include 
-#include 
-
-#include "msm_drv.h"
-#include "mdp5_kms.h"
-
-#define to_mdp5_mdss(x) container_of(x, struct mdp5_mdss, base)
-
-struct mdp5_mdss {
-   struct msm_mdss base;
-
-   void __iomem *mmio, *vbif;
-
-   struct clk *ahb_clk;
-   struct clk *axi_clk;
-   struct clk *vsync_clk;
-
-   struct {
-   volatile unsigned long enabled_mask;
-   struct irq_domain *domain;
-   } irqcontroller;
-};
-
-static inline void mdss_write(struct mdp5_mdss *mdp5_mdss, u32 reg, u32 data)
-{
-   msm_writel(data, mdp5_mdss->mmio + reg);
-}
-
-static inline u32 mdss_read(struct mdp5_mdss *mdp5_mdss, u32 reg)
-{
-   return msm_readl(mdp5_mdss->mmio + reg);
-}
-
-static irqreturn_t mdss_irq(int irq, void *arg)
-{
-   struct mdp5_mdss *mdp5_mdss = arg;
-   u32 intr;
-
-   intr = mdss_read(mdp5_mdss, REG_MDSS_HW_INTR_STATUS);
-
-   VERB("intr=%08x", intr);
-
-   while (intr) {
-   irq_hw_number_t hwirq = fls(intr) - 1;
-
-   generic_handle_domain_irq(mdp5_mdss->irqcontroller.domain, 
hwirq);
-   intr &= ~(1 << hwirq);
-   }
-
-   return IRQ_HANDLED;
-}
-
-/*
- * interrupt-controller implementation, so sub-blocks (MDP/HDMI/eDP/DSI/etc)
- * can register to get their irq's delivered
- */
-
-#define VALID_IRQS  (MDSS_HW_INTR_STATUS_INTR_MDP | \
-   MDSS_HW_INTR_STATUS_INTR_DSI0 | \
-   MDSS_HW_INTR_STATUS_INTR_DSI1 | \
-   MDSS_HW_INTR_STATUS_INTR_HDMI | \
-   MDSS_HW_INTR_STATUS_INTR_EDP)
-
-static void mdss_hw_mask_irq(struct irq_data *irqd)
-{
-   struct mdp5_mdss *mdp5_mdss = irq_data_get_irq_chip_data(irqd);
-
-   smp_mb__before_atomic();
-   clear_bit(irqd->hwirq, &mdp5_mdss->irqcontroller.enabled_mask);
-   smp_mb__after_atomic();
-}
-
-static void mdss_hw_unmask_irq(struct irq_data *irqd)
-{
-   struct mdp5_mdss *mdp5_mdss = irq_data_get_irq_chip_data(irqd);
-
-   smp_mb__before_atomic();
-   set_bit(irqd->hwirq, &mdp5_mdss->irqcontroller.enabled_mask);
-   smp_mb__after_atomic();
-}
-
-static struct irq_chip mdss_hw_irq_chip = {
-   .name   = "mdss",
-   .irq_mask   = mdss_hw_mask_irq,
-   .irq_unmask = mdss_hw_unmask_irq,
-};
-
-static int mdss_hw_irqdomain_map(struct irq_domain *d, unsigned int irq,
-irq_hw_number_t hwirq)
-{
-   struct mdp5_mdss *mdp5_mdss = d->host_data;
-
-   if (!(VALID_IRQS & (1 << hwirq)))
-   return -EPERM;
-
-   irq_set_chip_and_handler(irq, &mdss_hw_irq_chip, handle_level_irq);
-   irq_set_chip_data(irq, mdp5_mdss);
-
-   return 0;
-}
-
-static const struct irq_domain_ops mdss_hw_irqdomain_ops = {
-   .map = mdss_hw_irqdomain_map,
-   .xlate = irq_domain_xlate_onecell,
-};
-
-
-static int mdss_irq_domain_init(struct mdp5_mdss *mdp5_mdss)
-{
-   struct device *dev = mdp5_mdss->base.dev;
-  

[PATCH v4 4/6] drm/msm: stop using device's match data pointer

2022-03-25 Thread Dmitry Baryshkov
Let's make the match's data pointer a (sub-)driver's private data. The
only user currently is the msm_drm_init() function, using this data to
select kms_init callback. Pass this callback through the driver's
private data instead.

Reviewed-by: Stephen Boyd 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c  | 10 ---
 drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 14 +
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 11 ---
 drivers/gpu/drm/msm/msm_drv.c| 38 ++--
 drivers/gpu/drm/msm/msm_drv.h|  5 +---
 drivers/gpu/drm/msm/msm_kms.h|  4 ---
 drivers/gpu/drm/msm/msm_mdss.c   | 29 +++---
 7 files changed, 42 insertions(+), 69 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index e29796c4f27b..38627ccf3068 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1172,7 +1172,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
return rc;
 }
 
-struct msm_kms *dpu_kms_init(struct drm_device *dev)
+static int dpu_kms_init(struct drm_device *dev)
 {
struct msm_drm_private *priv;
struct dpu_kms *dpu_kms;
@@ -1180,7 +1180,7 @@ struct msm_kms *dpu_kms_init(struct drm_device *dev)
 
if (!dev) {
DPU_ERROR("drm device node invalid\n");
-   return ERR_PTR(-EINVAL);
+   return -EINVAL;
}
 
priv = dev->dev_private;
@@ -1189,11 +1189,11 @@ struct msm_kms *dpu_kms_init(struct drm_device *dev)
irq = irq_of_parse_and_map(dpu_kms->pdev->dev.of_node, 0);
if (irq < 0) {
DPU_ERROR("failed to get irq: %d\n", irq);
-   return ERR_PTR(irq);
+   return irq;
}
dpu_kms->base.irq = irq;
 
-   return &dpu_kms->base;
+   return 0;
 }
 
 static int dpu_bind(struct device *dev, struct device *master, void *data)
@@ -1204,6 +1204,8 @@ static int dpu_bind(struct device *dev, struct device 
*master, void *data)
struct dpu_kms *dpu_kms;
int ret = 0;
 
+   priv->kms_init = dpu_kms_init;
+
dpu_kms = devm_kzalloc(&pdev->dev, sizeof(*dpu_kms), GFP_KERNEL);
if (!dpu_kms)
return -ENOMEM;
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c 
b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
index 5dc839184aef..1a14f1d3cdf7 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
@@ -389,7 +389,7 @@ static void read_mdp_hw_revision(struct mdp4_kms *mdp4_kms,
DRM_DEV_INFO(dev->dev, "MDP4 version v%d.%d", *major, *minor);
 }
 
-struct msm_kms *mdp4_kms_init(struct drm_device *dev)
+static int mdp4_kms_init(struct drm_device *dev)
 {
struct platform_device *pdev = to_platform_device(dev->dev);
struct mdp4_platform_config *config = mdp4_get_config(pdev);
@@ -403,8 +403,7 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
mdp4_kms = kzalloc(sizeof(*mdp4_kms), GFP_KERNEL);
if (!mdp4_kms) {
DRM_DEV_ERROR(dev->dev, "failed to allocate kms\n");
-   ret = -ENOMEM;
-   goto fail;
+   return -ENOMEM;
}
 
ret = mdp_kms_init(&mdp4_kms->base, &kms_funcs);
@@ -551,12 +550,13 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
dev->mode_config.max_width = 2048;
dev->mode_config.max_height = 2048;
 
-   return kms;
+   return 0;
 
 fail:
if (kms)
mdp4_destroy(kms);
-   return ERR_PTR(ret);
+
+   return ret;
 }
 
 static struct mdp4_platform_config *mdp4_get_config(struct platform_device 
*dev)
@@ -583,6 +583,8 @@ static int mdp4_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
 
+   priv->kms_init = mdp4_kms_init;
+
platform_set_drvdata(pdev, priv);
 
/*
@@ -600,7 +602,7 @@ static int mdp4_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id mdp4_dt_match[] = {
-   { .compatible = "qcom,mdp4", .data = (void *)KMS_MDP4 },
+   { .compatible = "qcom,mdp4" },
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mdp4_dt_match);
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 3b92372e7bdf..0c78608832c3 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -544,7 +544,7 @@ static int get_clk(struct platform_device *pdev, struct clk 
**clkp,
return 0;
 }
 
-struct msm_kms *mdp5_kms_init(struct drm_device *dev)
+static int mdp5_kms_init(struct drm_device *dev)
 {
struct msm_drm_private *priv = dev->dev_private;
struct platform_device *pdev;
@@ -558,7 +558,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
/* priv->kms would have been populated by the MDP5 driver */
kms =

[PATCH v4 6/6] drm/msm: make mdp5/dpu devices master components

2022-03-25 Thread Dmitry Baryshkov
The msm_mdss serves several roles at this moment. It provides IRQ domain
used by MDP5 and DPU drivers but it also serves as a component master
for both those usecases. MDP4 (which does not have separate MDSS device)
is the component master on it's own.
Remove this assymmetry and make both MDP5 and DPU component masters too.
This removes a need to care about drm/components from msm_mdss driver,
removes an mdss pointer from struct msm_drm_private and simplifies the
interface between mdp5/dpu and msm_drv.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c  | 88 ++--
 drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 16 +
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 50 +-
 drivers/gpu/drm/msm/msm_drv.c| 32 -
 drivers/gpu/drm/msm/msm_drv.h|  6 +-
 drivers/gpu/drm/msm/msm_kms.h|  3 -
 drivers/gpu/drm/msm/msm_mdss.c   | 67 +++---
 7 files changed, 79 insertions(+), 183 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 38627ccf3068..7672e1d28665 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -380,9 +380,13 @@ static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms 
*dpu_kms)
struct icc_path *path0;
struct icc_path *path1;
struct drm_device *dev = dpu_kms->dev;
+   struct device *dpu_dev = dev->dev;
+   struct device *mdss_dev = dpu_dev->parent;
 
-   path0 = of_icc_get(dev->dev, "mdp0-mem");
-   path1 = of_icc_get(dev->dev, "mdp1-mem");
+   /* Interconnects are a part of MDSS device tree binding, not the
+* MDP/DPU device. */
+   path0 = of_icc_get(mdss_dev, "mdp0-mem");
+   path1 = of_icc_get(mdss_dev, "mdp1-mem");
 
if (IS_ERR_OR_NULL(path0))
return PTR_ERR_OR_ZERO(path0);
@@ -837,6 +841,9 @@ static void dpu_kms_destroy(struct msm_kms *kms)
_dpu_kms_hw_destroy(dpu_kms);
 
msm_kms_destroy(&dpu_kms->base);
+
+   if (dpu_kms->rpm_enabled)
+   pm_runtime_disable(&dpu_kms->pdev->dev);
 }
 
 static irqreturn_t dpu_irq(struct msm_kms *kms)
@@ -973,12 +980,16 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms)
struct iommu_domain *domain;
struct msm_gem_address_space *aspace;
struct msm_mmu *mmu;
+   struct device *dpu_dev = dpu_kms->dev->dev;
+   struct device *mdss_dev = dpu_dev->parent;
 
domain = iommu_domain_alloc(&platform_bus_type);
if (!domain)
return 0;
 
-   mmu = msm_iommu_new(dpu_kms->dev->dev, domain);
+   /* IOMMUs are a part of MDSS device tree binding, not the
+* MDP/DPU device. */
+   mmu = msm_iommu_new(mdss_dev, domain);
if (IS_ERR(mmu)) {
iommu_domain_free(domain);
return PTR_ERR(mmu);
@@ -1172,40 +1183,15 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
return rc;
 }
 
-static int dpu_kms_init(struct drm_device *dev)
-{
-   struct msm_drm_private *priv;
-   struct dpu_kms *dpu_kms;
-   int irq;
-
-   if (!dev) {
-   DPU_ERROR("drm device node invalid\n");
-   return -EINVAL;
-   }
-
-   priv = dev->dev_private;
-   dpu_kms = to_dpu_kms(priv->kms);
-
-   irq = irq_of_parse_and_map(dpu_kms->pdev->dev.of_node, 0);
-   if (irq < 0) {
-   DPU_ERROR("failed to get irq: %d\n", irq);
-   return irq;
-   }
-   dpu_kms->base.irq = irq;
-
-   return 0;
-}
-
-static int dpu_bind(struct device *dev, struct device *master, void *data)
+static int dpu_kms_init(struct drm_device *ddev)
 {
-   struct msm_drm_private *priv = dev_get_drvdata(master);
+   struct msm_drm_private *priv = ddev->dev_private;
+   struct device *dev = ddev->dev;
struct platform_device *pdev = to_platform_device(dev);
-   struct drm_device *ddev = priv->dev;
struct dpu_kms *dpu_kms;
+   int irq;
int ret = 0;
 
-   priv->kms_init = dpu_kms_init;
-
dpu_kms = devm_kzalloc(&pdev->dev, sizeof(*dpu_kms), GFP_KERNEL);
if (!dpu_kms)
return -ENOMEM;
@@ -1227,8 +1213,6 @@ static int dpu_bind(struct device *dev, struct device 
*master, void *data)
}
dpu_kms->num_clocks = ret;
 
-   platform_set_drvdata(pdev, dpu_kms);
-
ret = msm_kms_init(&dpu_kms->base, &kms_funcs);
if (ret) {
DPU_ERROR("failed to init kms, ret=%d\n", ret);
@@ -1242,31 +1226,25 @@ static int dpu_bind(struct device *dev, struct device 
*master, void *data)
 
priv->kms = &dpu_kms->base;
 
-   return ret;
-}
-
-static void dpu_unbind(struct device *dev, struct device *master, void *data)
-{
-   struct platform_device *pdev = to_platform_device(dev);
-   struct dpu_kms *dpu_kms = platform_get_drvdata(pdev);
+   irq = irq_of_parse_and_map(dpu_kms->pdev->d

[PATCH v4 2/6] drm/msm: remove extra indirection for msm_mdss

2022-03-25 Thread Dmitry Baryshkov
Since now there is just one mdss subdriver, drop all the indirection,
make msm_mdss struct completely opaque (and defined inside msm_mdss.c)
and call mdss functions directly.

Reviewed-by: Abhinav Kumar 
Reviewed-by: Stephen Boyd 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/msm_drv.c  |  29 +++
 drivers/gpu/drm/msm/msm_kms.h  |  16 ++--
 drivers/gpu/drm/msm/msm_mdss.c | 136 +++--
 3 files changed, 81 insertions(+), 100 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index a924fa46da9b..d3cce39c13bf 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -977,8 +977,8 @@ static int __maybe_unused msm_runtime_suspend(struct device 
*dev)
 
DBG("");
 
-   if (mdss && mdss->funcs)
-   return mdss->funcs->disable(mdss);
+   if (mdss)
+   return msm_mdss_disable(mdss);
 
return 0;
 }
@@ -990,8 +990,8 @@ static int __maybe_unused msm_runtime_resume(struct device 
*dev)
 
DBG("");
 
-   if (mdss && mdss->funcs)
-   return mdss->funcs->enable(mdss);
+   if (mdss)
+   return msm_mdss_enable(mdss);
 
return 0;
 }
@@ -1226,6 +1226,7 @@ static const struct component_master_ops msm_drm_ops = {
 static int msm_pdev_probe(struct platform_device *pdev)
 {
struct component_match *match = NULL;
+   struct msm_mdss *mdss;
struct msm_drm_private *priv;
int ret;
 
@@ -1237,20 +1238,22 @@ static int msm_pdev_probe(struct platform_device *pdev)
 
switch (get_mdp_ver(pdev)) {
case KMS_MDP5:
-   ret = msm_mdss_init(pdev, true);
+   mdss = msm_mdss_init(pdev, true);
break;
case KMS_DPU:
-   ret = msm_mdss_init(pdev, false);
+   mdss = msm_mdss_init(pdev, false);
break;
default:
-   ret = 0;
+   mdss = NULL;
break;
}
-   if (ret) {
-   platform_set_drvdata(pdev, NULL);
+   if (IS_ERR(mdss)) {
+   ret = PTR_ERR(mdss);
return ret;
}
 
+   priv->mdss = mdss;
+
if (get_mdp_ver(pdev)) {
ret = add_display_components(pdev, &match);
if (ret)
@@ -1277,8 +1280,8 @@ static int msm_pdev_probe(struct platform_device *pdev)
 fail:
of_platform_depopulate(&pdev->dev);
 
-   if (priv->mdss && priv->mdss->funcs)
-   priv->mdss->funcs->destroy(priv->mdss);
+   if (priv->mdss)
+   msm_mdss_destroy(priv->mdss);
 
return ret;
 }
@@ -1291,8 +1294,8 @@ static int msm_pdev_remove(struct platform_device *pdev)
component_master_del(&pdev->dev, &msm_drm_ops);
of_platform_depopulate(&pdev->dev);
 
-   if (mdss && mdss->funcs)
-   mdss->funcs->destroy(mdss);
+   if (mdss)
+   msm_mdss_destroy(mdss);
 
return 0;
 }
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 10d5ae3e76df..09c21994 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -201,18 +201,12 @@ struct msm_kms *dpu_kms_init(struct drm_device *dev);
 extern const struct of_device_id dpu_dt_match[];
 extern const struct of_device_id mdp5_dt_match[];
 
-struct msm_mdss_funcs {
-   int (*enable)(struct msm_mdss *mdss);
-   int (*disable)(struct msm_mdss *mdss);
-   void (*destroy)(struct msm_mdss *mdss);
-};
-
-struct msm_mdss {
-   struct device *dev;
-   const struct msm_mdss_funcs *funcs;
-};
+struct msm_mdss;
 
-int msm_mdss_init(struct platform_device *pdev, bool is_mdp5);
+struct msm_mdss *msm_mdss_init(struct platform_device *pdev, bool is_mdp5);
+int msm_mdss_enable(struct msm_mdss *mdss);
+int msm_mdss_disable(struct msm_mdss *mdss);
+void msm_mdss_destroy(struct msm_mdss *mdss);
 
 #define for_each_crtc_mask(dev, crtc, crtc_mask) \
drm_for_each_crtc(crtc, dev) \
diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index 71f3277bde32..62007a4f29a2 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -3,19 +3,16 @@
  * Copyright (c) 2018, The Linux Foundation
  */
 
+#include 
 #include 
 #include 
 #include 
 #include 
-
-#include "msm_drv.h"
-#include "msm_kms.h"
+#include 
 
 /* for DPU_HW_* defines */
 #include "disp/dpu1/dpu_hw_catalog.h"
 
-#define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
-
 #define HW_REV 0x0
 #define HW_INTR_STATUS 0x0010
 
@@ -23,8 +20,9 @@
 #define UBWC_CTRL_20x150
 #define UBWC_PREDICTION_MODE   0x154
 
-struct dpu_mdss {
-   struct msm_mdss base;
+struct msm_mdss {
+   struct device *dev;
+
void __iomem *mmio;
struct clk_bulk_data *clocks;
size_t num_clocks;
@@ -36,22 +34,22 @@ struct dpu_mdss {
 
 static void msm_mdss_irq(st

[PATCH v4 5/6] drm/msm: allow compile time selection of driver components

2022-03-25 Thread Dmitry Baryshkov
MSM DRM driver already allows one to compile out the DP or DSI support.
Add support for disabling other features like MDP4/MDP5/DPU drivers or
direct HDMI output support.

Suggested-by: Stephen Boyd 
Reviewed-by: Stephen Boyd 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/Kconfig   | 50 +--
 drivers/gpu/drm/msm/Makefile  | 24 ++---
 .../gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c  |  3 ++
 .../gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c  |  3 ++
 drivers/gpu/drm/msm/msm_drv.h | 33 
 drivers/gpu/drm/msm/msm_mdss.c| 13 -
 6 files changed, 115 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 9b019598e042..96b01873ce36 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -46,12 +46,39 @@ config DRM_MSM_GPU_SUDO
  Only use this if you are a driver developer.  This should *not*
  be enabled for production kernels.  If unsure, say N.
 
-config DRM_MSM_HDMI_HDCP
-   bool "Enable HDMI HDCP support in MSM DRM driver"
+config DRM_MSM_MDSS
+   bool
+   depends on DRM_MSM
+   default n
+
+config DRM_MSM_MDP4
+   bool "Enable MDP4 support in MSM DRM driver"
depends on DRM_MSM
default y
help
- Choose this option to enable HDCP state machine
+ Compile in support for the Mobile Display Processor v4 (MDP4) in
+ the MSM DRM driver. It is the older display controller found in
+ devices using APQ8064/MSM8960/MSM8x60 platforms.
+
+config DRM_MSM_MDP5
+   bool "Enable MDP5 support in MSM DRM driver"
+   depends on DRM_MSM
+   select DRM_MSM_MDSS
+   default y
+   help
+ Compile in support for the Mobile Display Processor v5 (MDP5) in
+ the MSM DRM driver. It is the display controller found in devices
+ using e.g. APQ8016/MSM8916/APQ8096/MSM8996/MSM8974/SDM6x0 platforms.
+
+config DRM_MSM_DPU
+   bool "Enable DPU support in MSM DRM driver"
+   depends on DRM_MSM
+   select DRM_MSM_MDSS
+   default y
+   help
+ Compile in support for the Display Processing Unit in
+ the MSM DRM driver. It is the display controller found in devices
+ using e.g. SDM845 and newer platforms.
 
 config DRM_MSM_DP
bool "Enable DisplayPort support in MSM DRM driver"
@@ -116,3 +143,20 @@ config DRM_MSM_DSI_7NM_PHY
help
  Choose this option if DSI PHY on SM8150/SM8250/SC7280 is used on
  the platform.
+
+config DRM_MSM_HDMI
+   bool "Enable HDMI support in MSM DRM driver"
+   depends on DRM_MSM
+   default y
+   help
+ Compile in support for the HDMI output MSM DRM driver. It can
+ be a primary or a secondary display on device. Note that this is used
+ only for the direct HDMI output. If the device outputs HDMI data
+ throught some kind of DSI-to-HDMI bridge, this option can be disabled.
+
+config DRM_MSM_HDMI_HDCP
+   bool "Enable HDMI HDCP support in MSM DRM driver"
+   depends on DRM_MSM && DRM_MSM_HDMI
+   default y
+   help
+ Choose this option to enable HDCP state machine
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index e76927b42033..3dc576309255 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -16,6 +16,8 @@ msm-y := \
adreno/a6xx_gpu.o \
adreno/a6xx_gmu.o \
adreno/a6xx_hfi.o \
+
+msm-$(CONFIG_DRM_MSM_HDMI) += \
hdmi/hdmi.o \
hdmi/hdmi_audio.o \
hdmi/hdmi_bridge.o \
@@ -27,9 +29,10 @@ msm-y := \
hdmi/hdmi_phy_8x60.o \
hdmi/hdmi_phy_8x74.o \
hdmi/hdmi_pll_8960.o \
-   disp/mdp_format.o \
-   disp/mdp_kms.o \
+
+msm-$(CONFIG_DRM_MSM_MDP4) += \
disp/mdp4/mdp4_crtc.o \
+   disp/mdp4/mdp4_dsi_encoder.o \
disp/mdp4/mdp4_dtv_encoder.o \
disp/mdp4/mdp4_lcdc_encoder.o \
disp/mdp4/mdp4_lvds_connector.o \
@@ -37,7 +40,10 @@ msm-y := \
disp/mdp4/mdp4_irq.o \
disp/mdp4/mdp4_kms.o \
disp/mdp4/mdp4_plane.o \
+
+msm-$(CONFIG_DRM_MSM_MDP5) += \
disp/mdp5/mdp5_cfg.o \
+   disp/mdp5/mdp5_cmd_encoder.o \
disp/mdp5/mdp5_ctl.o \
disp/mdp5/mdp5_crtc.o \
disp/mdp5/mdp5_encoder.o \
@@ -47,6 +53,8 @@ msm-y := \
disp/mdp5/mdp5_mixer.o \
disp/mdp5/mdp5_plane.o \
disp/mdp5/mdp5_smp.o \
+
+msm-$(CONFIG_DRM_MSM_DPU) += \
disp/dpu1/dpu_core_perf.o \
disp/dpu1/dpu_crtc.o \
disp/dpu1/dpu_encoder.o \
@@ -69,6 +77,13 @@ msm-y := \
disp/dpu1/dpu_plane.o \
disp/dpu1/dpu_rm.o \
disp/dpu1/dpu_vbif.o \
+
+msm-$(CONFIG_DRM_MSM_MDSS) += \
+   msm_mdss.o \
+
+msm-y += \
+   disp/mdp_format.o \
+   disp/mdp_kms.o \
disp/msm_disp_snapshot.o \
disp/msm_disp_snapshot_util.o \
msm_atomic.o \
@

Re: [PATCH v5 02/13] drm/msm/dsi: Pass DSC params to drm_panel

2022-03-25 Thread Dmitry Baryshkov

On 25/03/2022 14:05, Vinod Koul wrote:

When DSC is enabled, we need to get the DSC parameters from the panel
driver, so add a dsc parameter in panel to fetch and pass DSC
configuration for DSI panels to DPU encoder, which will enable and
then configure DSC hardware blocks accordingly.

Signed-off-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
  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(&msm_host->base);
+
+   if (panel && panel->dsc) {
+   struct msm_display_dsc_config *dsc = msm_host->dsc;
+
+   if (!dsc) {
+   dsc = devm_kzalloc(&msm_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;


struct msm_display_info was moved from msm_drv.h to dpu_encoder.h.

Please rebase your patches on top of msm/msm-next branch


@@ -126,6 +127,7 @@ struct msm_display_info {
uint32_t num_

[PATCH 0/9] drm/edid: constify EDID parsing

2022-03-25 Thread Jani Nikula
Remove accidental (?) EDID modification while parsing, and constify EDID
in most places during EDID parsing.

In the future I'll want more clarity on who modifies the EDID and where,
and I'll want the compiler to help.

The EDID is still mutable in places that do validity checking and try to
fix it in the process. I'll probably want to split the two into separate
check and fix steps too, but that's for another series.

This is based on current drm-tip, without the CEA iterators work.


BR,
Jani.


Cc: Ville Syrjälä 

Jani Nikula (9):
  drm/edid: don't modify EDID while parsing
  drm/edid: pass a timing pointer to is_display_descriptor()
  drm/edid: use struct detailed_timing member access in is_rb()
  drm/edid: use struct detailed_timing member access in gtf2 functions
  drm/edid: constify struct detailed_timing in lower level parsing
  drm/edid: constify struct detailed_timing in parsing callbacks
  drm/edid: constify struct edid passed to detailed blocks
  drm/edid: constify struct edid passed around in callbacks and closure
  drm/edid: add more general struct edid constness in the interfaces

 drivers/gpu/drm/drm_edid.c | 272 -
 include/drm/drm_edid.h |  10 +-
 2 files changed, 153 insertions(+), 129 deletions(-)

-- 
2.30.2



[PATCH 1/9] drm/edid: don't modify EDID while parsing

2022-03-25 Thread Jani Nikula
We'll want to keep the EDID immutable while parsing. Stop modifying the
EDID because of the quirks.

In theory, this does have userspace implications, but the userspace is
supposed to use the modes exposed via KMS API, not by parsing the EDID
directly.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index cc7bd58369df..1b552fe54f38 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2740,9 +2740,9 @@ static struct drm_display_mode *drm_mode_detailed(struct 
drm_device *dev,
return NULL;
 
if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH)
-   timing->pixel_clock = cpu_to_le16(1088);
-
-   mode->clock = le16_to_cpu(timing->pixel_clock) * 10;
+   mode->clock = 1088 * 10;
+   else
+   mode->clock = le16_to_cpu(timing->pixel_clock) * 10;
 
mode->hdisplay = hactive;
mode->hsync_start = mode->hdisplay + hsync_offset;
@@ -2763,14 +2763,14 @@ static struct drm_display_mode 
*drm_mode_detailed(struct drm_device *dev,
drm_mode_do_interlace_quirk(mode, pt);
 
if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
-   pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | 
DRM_EDID_PT_VSYNC_POSITIVE;
+   mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC;
+   } else {
+   mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
+   DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
+   mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
+   DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
}
 
-   mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
-   DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
-   mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
-   DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
-
 set_size:
mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4;
mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 
8;
-- 
2.30.2



[PATCH 2/9] drm/edid: pass a timing pointer to is_display_descriptor()

2022-03-25 Thread Jani Nikula
Use struct member access instead of direct offsets to avoid lots of
casts all over the place.

Use BUILD_BUG_ON() for sanity check.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 26 +++---
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 1b552fe54f38..48707eef1dc2 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2331,10 +2331,14 @@ struct drm_display_mode *drm_mode_find_dmt(struct 
drm_device *dev,
 }
 EXPORT_SYMBOL(drm_mode_find_dmt);
 
-static bool is_display_descriptor(const u8 d[18], u8 tag)
+static bool is_display_descriptor(const struct detailed_timing *timing, u8 
type)
 {
-   return d[0] == 0x00 && d[1] == 0x00 &&
-   d[2] == 0x00 && d[3] == tag;
+   BUILD_BUG_ON(offsetof(typeof(*timing), pixel_clock) != 0);
+   BUILD_BUG_ON(offsetof(typeof(*timing), data.other_data.pad1) != 2);
+   BUILD_BUG_ON(offsetof(typeof(*timing), data.other_data.type) != 3);
+
+   return timing->pixel_clock == 0 && timing->data.other_data.pad1 == 0 &&
+   timing->data.other_data.type == type;
 }
 
 static bool is_detailed_timing_descriptor(const u8 d[18])
@@ -2405,7 +2409,7 @@ is_rb(struct detailed_timing *t, void *data)
 {
u8 *r = (u8 *)t;
 
-   if (!is_display_descriptor(r, EDID_DETAIL_MONITOR_RANGE))
+   if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_RANGE))
return;
 
if (r[15] & 0x10)
@@ -2431,7 +2435,7 @@ find_gtf2(struct detailed_timing *t, void *data)
 {
u8 *r = (u8 *)t;
 
-   if (!is_display_descriptor(r, EDID_DETAIL_MONITOR_RANGE))
+   if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_RANGE))
return;
 
if (r[10] == 0x02)
@@ -2987,7 +2991,7 @@ do_inferred_modes(struct detailed_timing *timing, void *c)
struct detailed_non_pixel *data = &timing->data.other_data;
struct detailed_data_monitor_range *range = &data->data.range;
 
-   if (!is_display_descriptor((const u8 *)timing, 
EDID_DETAIL_MONITOR_RANGE))
+   if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE))
return;
 
closure->modes += drm_dmt_modes_for_range(closure->connector,
@@ -3067,7 +3071,7 @@ do_established_modes(struct detailed_timing *timing, void 
*c)
 {
struct detailed_mode_closure *closure = c;
 
-   if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_EST_TIMINGS))
+   if (!is_display_descriptor(timing, EDID_DETAIL_EST_TIMINGS))
return;
 
closure->modes += drm_est3_modes(closure->connector, timing);
@@ -3122,7 +3126,7 @@ do_standard_modes(struct detailed_timing *timing, void *c)
struct edid *edid = closure->edid;
int i;
 
-   if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_STD_MODES))
+   if (!is_display_descriptor(timing, EDID_DETAIL_STD_MODES))
return;
 
for (i = 0; i < 6; i++) {
@@ -3231,7 +3235,7 @@ do_cvt_mode(struct detailed_timing *timing, void *c)
 {
struct detailed_mode_closure *closure = c;
 
-   if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_CVT_3BYTE))
+   if (!is_display_descriptor(timing, EDID_DETAIL_CVT_3BYTE))
return;
 
closure->modes += drm_cvt_modes(closure->connector, timing);
@@ -4491,7 +4495,7 @@ drm_parse_hdmi_vsdb_audio(struct drm_connector 
*connector, const u8 *db)
 static void
 monitor_name(struct detailed_timing *t, void *data)
 {
-   if (!is_display_descriptor((const u8 *)t, EDID_DETAIL_MONITOR_NAME))
+   if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_NAME))
return;
 
*(u8 **)data = t->data.other_data.data.str.str;
@@ -5226,7 +5230,7 @@ void get_monitor_range(struct detailed_timing *timing,
const struct detailed_non_pixel *data = &timing->data.other_data;
const struct detailed_data_monitor_range *range = &data->data.range;
 
-   if (!is_display_descriptor((const u8 *)timing, 
EDID_DETAIL_MONITOR_RANGE))
+   if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE))
return;
 
/*
-- 
2.30.2



[PATCH 3/9] drm/edid: use struct detailed_timing member access in is_rb()

2022-03-25 Thread Jani Nikula
Use struct detailed_timing member access instead of direct offsets to
avoid casting.

Use BUILD_BUG_ON() for sanity check.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 

---

Note: Why can we use range.formula.cvt.flags directly in is_rb() while
gtf2 functions check for range.flags == 0x02 first to ensure it's gtf2?
---
 drivers/gpu/drm/drm_edid.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 48707eef1dc2..5396fa78e864 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2405,15 +2405,17 @@ drm_for_each_detailed_block(u8 *raw_edid, detailed_cb 
*cb, void *closure)
 }
 
 static void
-is_rb(struct detailed_timing *t, void *data)
+is_rb(struct detailed_timing *timing, void *data)
 {
-   u8 *r = (u8 *)t;
+   bool *res = data;
 
-   if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_RANGE))
+   if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE))
return;
 
-   if (r[15] & 0x10)
-   *(bool *)data = true;
+   BUILD_BUG_ON(offsetof(typeof(*timing), 
data.other_data.data.range.formula.cvt.flags) != 15);
+
+   if (timing->data.other_data.data.range.formula.cvt.flags & 0x10)
+   *res = true;
 }
 
 /* EDID 1.4 defines this explicitly.  For EDID 1.3, we guess, badly. */
-- 
2.30.2



[PATCH 4/9] drm/edid: use struct detailed_timing member access in gtf2 functions

2022-03-25 Thread Jani Nikula
Use struct detailed_timing member access instead of direct offsets to
avoid casting.

Use BUILD_BUG_ON() for sanity check.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 57 +-
 1 file changed, 37 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 5396fa78e864..a9df75cdcc5b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2433,61 +2433,78 @@ drm_monitor_supports_rb(struct edid *edid)
 }
 
 static void
-find_gtf2(struct detailed_timing *t, void *data)
+find_gtf2(struct detailed_timing *timing, void *data)
 {
-   u8 *r = (u8 *)t;
+   struct detailed_timing **res = data;
 
-   if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_RANGE))
+   if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE))
return;
 
-   if (r[10] == 0x02)
-   *(u8 **)data = r;
+   BUILD_BUG_ON(offsetof(typeof(*timing), 
data.other_data.data.range.flags) != 10);
+
+   if (timing->data.other_data.data.range.flags == 0x02)
+   *res = timing;
 }
 
 /* Secondary GTF curve kicks in above some break frequency */
 static int
 drm_gtf2_hbreak(struct edid *edid)
 {
-   u8 *r = NULL;
+   struct detailed_timing *timing = NULL;
+
+   drm_for_each_detailed_block((u8 *)edid, find_gtf2, &timing);
 
-   drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
-   return r ? (r[12] * 2) : 0;
+   BUILD_BUG_ON(offsetof(typeof(*timing), 
data.other_data.data.range.formula.gtf2.hfreq_start_khz) != 12);
+
+   return timing ? 
timing->data.other_data.data.range.formula.gtf2.hfreq_start_khz * 2 : 0;
 }
 
 static int
 drm_gtf2_2c(struct edid *edid)
 {
-   u8 *r = NULL;
+   struct detailed_timing *timing = NULL;
+
+   drm_for_each_detailed_block((u8 *)edid, find_gtf2, &timing);
+
+   BUILD_BUG_ON(offsetof(typeof(*timing), 
data.other_data.data.range.formula.gtf2.c) != 13);
 
-   drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
-   return r ? r[13] : 0;
+   return timing ? timing->data.other_data.data.range.formula.gtf2.c : 0;
 }
 
 static int
 drm_gtf2_m(struct edid *edid)
 {
-   u8 *r = NULL;
+   struct detailed_timing *timing = NULL;
 
-   drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
-   return r ? (r[15] << 8) + r[14] : 0;
+   drm_for_each_detailed_block((u8 *)edid, find_gtf2, &timing);
+
+   BUILD_BUG_ON(offsetof(typeof(*timing), 
data.other_data.data.range.formula.gtf2.m) != 14);
+
+   return timing ? 
le16_to_cpu(timing->data.other_data.data.range.formula.gtf2.m) : 0;
 }
 
 static int
 drm_gtf2_k(struct edid *edid)
 {
-   u8 *r = NULL;
+   struct detailed_timing *timing = NULL;
+
+   drm_for_each_detailed_block((u8 *)edid, find_gtf2, &timing);
 
-   drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
-   return r ? r[16] : 0;
+   BUILD_BUG_ON(offsetof(typeof(*timing), 
data.other_data.data.range.formula.gtf2.k) != 16);
+
+   return timing ? timing->data.other_data.data.range.formula.gtf2.k : 0;
 }
 
 static int
 drm_gtf2_2j(struct edid *edid)
 {
-   u8 *r = NULL;
+   struct detailed_timing *timing = NULL;
+
+   drm_for_each_detailed_block((u8 *)edid, find_gtf2, &timing);
+
+   BUILD_BUG_ON(offsetof(typeof(*timing), 
data.other_data.data.range.formula.gtf2.j) != 17);
 
-   drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
-   return r ? r[17] : 0;
+   return timing ? timing->data.other_data.data.range.formula.gtf2.j : 0;
 }
 
 /**
-- 
2.30.2



[PATCH 5/9] drm/edid: constify struct detailed_timing in lower level parsing

2022-03-25 Thread Jani Nikula
Start constifying the struct detailed_timing pointers being passed
around from bottom up.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 40 +++---
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index a9df75cdcc5b..593f151c1155 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2555,7 +2555,7 @@ static int drm_mode_hsync(const struct drm_display_mode 
*mode)
  */
 static struct drm_display_mode *
 drm_mode_std(struct drm_connector *connector, struct edid *edid,
-struct std_timing *t)
+const struct std_timing *t)
 {
struct drm_device *dev = connector->dev;
struct drm_display_mode *m, *mode = NULL;
@@ -2673,7 +2673,7 @@ drm_mode_std(struct drm_connector *connector, struct edid 
*edid,
  */
 static void
 drm_mode_do_interlace_quirk(struct drm_display_mode *mode,
-   struct detailed_pixel_timing *pt)
+   const struct detailed_pixel_timing *pt)
 {
int i;
static const struct {
@@ -2717,11 +2717,11 @@ drm_mode_do_interlace_quirk(struct drm_display_mode 
*mode,
  */
 static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
  struct edid *edid,
- struct detailed_timing 
*timing,
+ const struct detailed_timing 
*timing,
  u32 quirks)
 {
struct drm_display_mode *mode;
-   struct detailed_pixel_timing *pt = &timing->data.pixel_data;
+   const struct detailed_pixel_timing *pt = &timing->data.pixel_data;
unsigned hactive = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo;
unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo;
unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo;
@@ -2816,7 +2816,7 @@ static struct drm_display_mode *drm_mode_detailed(struct 
drm_device *dev,
 
 static bool
 mode_in_hsync_range(const struct drm_display_mode *mode,
-   struct edid *edid, u8 *t)
+   struct edid *edid, const u8 *t)
 {
int hsync, hmin, hmax;
 
@@ -2833,7 +2833,7 @@ mode_in_hsync_range(const struct drm_display_mode *mode,
 
 static bool
 mode_in_vsync_range(const struct drm_display_mode *mode,
-   struct edid *edid, u8 *t)
+   struct edid *edid, const u8 *t)
 {
int vsync, vmin, vmax;
 
@@ -2849,7 +2849,7 @@ mode_in_vsync_range(const struct drm_display_mode *mode,
 }
 
 static u32
-range_pixel_clock(struct edid *edid, u8 *t)
+range_pixel_clock(struct edid *edid, const u8 *t)
 {
/* unspecified */
if (t[9] == 0 || t[9] == 255)
@@ -2865,10 +2865,10 @@ range_pixel_clock(struct edid *edid, u8 *t)
 
 static bool
 mode_in_range(const struct drm_display_mode *mode, struct edid *edid,
- struct detailed_timing *timing)
+ const struct detailed_timing *timing)
 {
u32 max_clock;
-   u8 *t = (u8 *)timing;
+   const u8 *t = (const u8 *)timing;
 
if (!mode_in_hsync_range(mode, edid, t))
return false;
@@ -2911,7 +2911,7 @@ static bool valid_inferred_mode(const struct 
drm_connector *connector,
 
 static int
 drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid,
-   struct detailed_timing *timing)
+   const struct detailed_timing *timing)
 {
int i, modes = 0;
struct drm_display_mode *newmode;
@@ -2946,7 +2946,7 @@ void drm_mode_fixup_1366x768(struct drm_display_mode 
*mode)
 
 static int
 drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
-   struct detailed_timing *timing)
+   const struct detailed_timing *timing)
 {
int i, modes = 0;
struct drm_display_mode *newmode;
@@ -2975,7 +2975,7 @@ drm_gtf_modes_for_range(struct drm_connector *connector, 
struct edid *edid,
 
 static int
 drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid,
-   struct detailed_timing *timing)
+   const struct detailed_timing *timing)
 {
int i, modes = 0;
struct drm_display_mode *newmode;
@@ -3007,8 +3007,8 @@ static void
 do_inferred_modes(struct detailed_timing *timing, void *c)
 {
struct detailed_mode_closure *closure = c;
-   struct detailed_non_pixel *data = &timing->data.other_data;
-   struct detailed_data_monitor_range *range = &data->data.range;
+   const struct detailed_non_pixel *data = &timing->data.other_data;
+   const struct detailed_data_monitor_range *range = &data->data.range;
 
if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE))
return;
@@ -3057,11 +3057,11 

[PATCH 6/9] drm/edid: constify struct detailed_timing in parsing callbacks

2022-03-25 Thread Jani Nikula
Moving one level higher, constify struct detailed_timing pointers in
callbacks.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 40 --
 1 file changed, 21 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 593f151c1155..c006b09066bb 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2346,7 +2346,7 @@ static bool is_detailed_timing_descriptor(const u8 d[18])
return d[0] != 0x00 || d[1] != 0x00;
 }
 
-typedef void detailed_cb(struct detailed_timing *timing, void *closure);
+typedef void detailed_cb(const struct detailed_timing *timing, void *closure);
 
 static void
 cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure)
@@ -2405,7 +2405,7 @@ drm_for_each_detailed_block(u8 *raw_edid, detailed_cb 
*cb, void *closure)
 }
 
 static void
-is_rb(struct detailed_timing *timing, void *data)
+is_rb(const struct detailed_timing *timing, void *data)
 {
bool *res = data;
 
@@ -2433,9 +2433,9 @@ drm_monitor_supports_rb(struct edid *edid)
 }
 
 static void
-find_gtf2(struct detailed_timing *timing, void *data)
+find_gtf2(const struct detailed_timing *timing, void *data)
 {
-   struct detailed_timing **res = data;
+   const struct detailed_timing **res = data;
 
if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE))
return;
@@ -2450,7 +2450,7 @@ find_gtf2(struct detailed_timing *timing, void *data)
 static int
 drm_gtf2_hbreak(struct edid *edid)
 {
-   struct detailed_timing *timing = NULL;
+   const struct detailed_timing *timing = NULL;
 
drm_for_each_detailed_block((u8 *)edid, find_gtf2, &timing);
 
@@ -2462,7 +2462,7 @@ drm_gtf2_hbreak(struct edid *edid)
 static int
 drm_gtf2_2c(struct edid *edid)
 {
-   struct detailed_timing *timing = NULL;
+   const struct detailed_timing *timing = NULL;
 
drm_for_each_detailed_block((u8 *)edid, find_gtf2, &timing);
 
@@ -2474,7 +2474,7 @@ drm_gtf2_2c(struct edid *edid)
 static int
 drm_gtf2_m(struct edid *edid)
 {
-   struct detailed_timing *timing = NULL;
+   const struct detailed_timing *timing = NULL;
 
drm_for_each_detailed_block((u8 *)edid, find_gtf2, &timing);
 
@@ -2486,7 +2486,7 @@ drm_gtf2_m(struct edid *edid)
 static int
 drm_gtf2_k(struct edid *edid)
 {
-   struct detailed_timing *timing = NULL;
+   const struct detailed_timing *timing = NULL;
 
drm_for_each_detailed_block((u8 *)edid, find_gtf2, &timing);
 
@@ -2498,7 +2498,7 @@ drm_gtf2_k(struct edid *edid)
 static int
 drm_gtf2_2j(struct edid *edid)
 {
-   struct detailed_timing *timing = NULL;
+   const struct detailed_timing *timing = NULL;
 
drm_for_each_detailed_block((u8 *)edid, find_gtf2, &timing);
 
@@ -3004,7 +3004,7 @@ drm_cvt_modes_for_range(struct drm_connector *connector, 
struct edid *edid,
 }
 
 static void
-do_inferred_modes(struct detailed_timing *timing, void *c)
+do_inferred_modes(const struct detailed_timing *timing, void *c)
 {
struct detailed_mode_closure *closure = c;
const struct detailed_non_pixel *data = &timing->data.other_data;
@@ -3086,7 +3086,7 @@ drm_est3_modes(struct drm_connector *connector, const 
struct detailed_timing *ti
 }
 
 static void
-do_established_modes(struct detailed_timing *timing, void *c)
+do_established_modes(const struct detailed_timing *timing, void *c)
 {
struct detailed_mode_closure *closure = c;
 
@@ -3137,7 +3137,7 @@ add_established_modes(struct drm_connector *connector, 
struct edid *edid)
 }
 
 static void
-do_standard_modes(struct detailed_timing *timing, void *c)
+do_standard_modes(const struct detailed_timing *timing, void *c)
 {
struct detailed_mode_closure *closure = c;
const struct detailed_non_pixel *data = &timing->data.other_data;
@@ -3250,7 +3250,7 @@ static int drm_cvt_modes(struct drm_connector *connector,
 }
 
 static void
-do_cvt_mode(struct detailed_timing *timing, void *c)
+do_cvt_mode(const struct detailed_timing *timing, void *c)
 {
struct detailed_mode_closure *closure = c;
 
@@ -3279,7 +3279,7 @@ add_cvt_modes(struct drm_connector *connector, struct 
edid *edid)
 static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode);
 
 static void
-do_detailed_mode(struct detailed_timing *timing, void *c)
+do_detailed_mode(const struct detailed_timing *timing, void *c)
 {
struct detailed_mode_closure *closure = c;
struct drm_display_mode *newmode;
@@ -4512,17 +4512,19 @@ drm_parse_hdmi_vsdb_audio(struct drm_connector 
*connector, const u8 *db)
 }
 
 static void
-monitor_name(struct detailed_timing *t, void *data)
+monitor_name(const struct detailed_timing *timing, void *data)
 {
-   if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_NAME))
+   const char **res = data;
+
+   if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_NAME))
return;
 
-   *

[PATCH 8/9] drm/edid: constify struct edid passed around in callbacks and closure

2022-03-25 Thread Jani Nikula
Finalize detailed timing parsing constness by making struct edid also
const in callbacks and closure.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 48 +++---
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index fad792ef2c79..fae6f39897c8 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -97,7 +97,7 @@ static int oui(u8 first, u8 second, u8 third)
 
 struct detailed_mode_closure {
struct drm_connector *connector;
-   struct edid *edid;
+   const struct edid *edid;
bool preferred;
u32 quirks;
int modes;
@@ -2419,7 +2419,7 @@ is_rb(const struct detailed_timing *timing, void *data)
 
 /* EDID 1.4 defines this explicitly.  For EDID 1.3, we guess, badly. */
 static bool
-drm_monitor_supports_rb(struct edid *edid)
+drm_monitor_supports_rb(const struct edid *edid)
 {
if (edid->revision >= 4) {
bool ret = false;
@@ -2447,7 +2447,7 @@ find_gtf2(const struct detailed_timing *timing, void 
*data)
 
 /* Secondary GTF curve kicks in above some break frequency */
 static int
-drm_gtf2_hbreak(struct edid *edid)
+drm_gtf2_hbreak(const struct edid *edid)
 {
const struct detailed_timing *timing = NULL;
 
@@ -2459,7 +2459,7 @@ drm_gtf2_hbreak(struct edid *edid)
 }
 
 static int
-drm_gtf2_2c(struct edid *edid)
+drm_gtf2_2c(const struct edid *edid)
 {
const struct detailed_timing *timing = NULL;
 
@@ -2471,7 +2471,7 @@ drm_gtf2_2c(struct edid *edid)
 }
 
 static int
-drm_gtf2_m(struct edid *edid)
+drm_gtf2_m(const struct edid *edid)
 {
const struct detailed_timing *timing = NULL;
 
@@ -2483,7 +2483,7 @@ drm_gtf2_m(struct edid *edid)
 }
 
 static int
-drm_gtf2_k(struct edid *edid)
+drm_gtf2_k(const struct edid *edid)
 {
const struct detailed_timing *timing = NULL;
 
@@ -2495,7 +2495,7 @@ drm_gtf2_k(struct edid *edid)
 }
 
 static int
-drm_gtf2_2j(struct edid *edid)
+drm_gtf2_2j(const struct edid *edid)
 {
const struct detailed_timing *timing = NULL;
 
@@ -2510,7 +2510,7 @@ drm_gtf2_2j(struct edid *edid)
  * standard_timing_level - get std. timing level(CVT/GTF/DMT)
  * @edid: EDID block to scan
  */
-static int standard_timing_level(struct edid *edid)
+static int standard_timing_level(const struct edid *edid)
 {
if (edid->revision >= 2) {
if (edid->revision >= 4 && (edid->features & 
DRM_EDID_FEATURE_DEFAULT_GTF))
@@ -2553,7 +2553,7 @@ static int drm_mode_hsync(const struct drm_display_mode 
*mode)
  * and convert them into a real mode using CVT/GTF/DMT.
  */
 static struct drm_display_mode *
-drm_mode_std(struct drm_connector *connector, struct edid *edid,
+drm_mode_std(struct drm_connector *connector, const struct edid *edid,
 const struct std_timing *t)
 {
struct drm_device *dev = connector->dev;
@@ -2715,7 +2715,7 @@ drm_mode_do_interlace_quirk(struct drm_display_mode *mode,
  * return a new struct drm_display_mode.
  */
 static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
- struct edid *edid,
+ const struct edid *edid,
  const struct detailed_timing 
*timing,
  u32 quirks)
 {
@@ -2815,7 +2815,7 @@ static struct drm_display_mode *drm_mode_detailed(struct 
drm_device *dev,
 
 static bool
 mode_in_hsync_range(const struct drm_display_mode *mode,
-   struct edid *edid, const u8 *t)
+   const struct edid *edid, const u8 *t)
 {
int hsync, hmin, hmax;
 
@@ -2832,7 +2832,7 @@ mode_in_hsync_range(const struct drm_display_mode *mode,
 
 static bool
 mode_in_vsync_range(const struct drm_display_mode *mode,
-   struct edid *edid, const u8 *t)
+   const struct edid *edid, const u8 *t)
 {
int vsync, vmin, vmax;
 
@@ -2848,7 +2848,7 @@ mode_in_vsync_range(const struct drm_display_mode *mode,
 }
 
 static u32
-range_pixel_clock(struct edid *edid, const u8 *t)
+range_pixel_clock(const struct edid *edid, const u8 *t)
 {
/* unspecified */
if (t[9] == 0 || t[9] == 255)
@@ -2863,7 +2863,7 @@ range_pixel_clock(struct edid *edid, const u8 *t)
 }
 
 static bool
-mode_in_range(const struct drm_display_mode *mode, struct edid *edid,
+mode_in_range(const struct drm_display_mode *mode, const struct edid *edid,
  const struct detailed_timing *timing)
 {
u32 max_clock;
@@ -2909,7 +2909,7 @@ static bool valid_inferred_mode(const struct 
drm_connector *connector,
 }
 
 static int
-drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid,
+drm_dmt_modes_for_range(struct drm_connector *connector, const struct edid 
*edid,
const struct detailed_timing *timing)
 {
int i, modes

[PATCH 7/9] drm/edid: constify struct edid passed to detailed blocks

2022-03-25 Thread Jani Nikula
Constify the first level of struct edid in detailed timing parsing. Also
switch to struct edid instead of u8.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 48 ++
 1 file changed, 23 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index c006b09066bb..fad792ef2c79 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2349,38 +2349,37 @@ static bool is_detailed_timing_descriptor(const u8 
d[18])
 typedef void detailed_cb(const struct detailed_timing *timing, void *closure);
 
 static void
-cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure)
+cea_for_each_detailed_block(const u8 *ext, detailed_cb *cb, void *closure)
 {
int i, n;
u8 d = ext[0x02];
-   u8 *det_base = ext + d;
+   const u8 *det_base = ext + d;
 
if (d < 4 || d > 127)
return;
 
n = (127 - d) / 18;
for (i = 0; i < n; i++)
-   cb((struct detailed_timing *)(det_base + 18 * i), closure);
+   cb((const struct detailed_timing *)(det_base + 18 * i), 
closure);
 }
 
 static void
-vtb_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure)
+vtb_for_each_detailed_block(const u8 *ext, detailed_cb *cb, void *closure)
 {
unsigned int i, n = min((int)ext[0x02], 6);
-   u8 *det_base = ext + 5;
+   const u8 *det_base = ext + 5;
 
if (ext[0x01] != 1)
return; /* unknown version */
 
for (i = 0; i < n; i++)
-   cb((struct detailed_timing *)(det_base + 18 * i), closure);
+   cb((const struct detailed_timing *)(det_base + 18 * i), 
closure);
 }
 
 static void
-drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure)
+drm_for_each_detailed_block(const struct edid *edid, detailed_cb *cb, void 
*closure)
 {
int i;
-   struct edid *edid = (struct edid *)raw_edid;
 
if (edid == NULL)
return;
@@ -2388,8 +2387,8 @@ drm_for_each_detailed_block(u8 *raw_edid, detailed_cb 
*cb, void *closure)
for (i = 0; i < EDID_DETAILED_TIMINGS; i++)
cb(&(edid->detailed_timings[i]), closure);
 
-   for (i = 1; i <= raw_edid[0x7e]; i++) {
-   u8 *ext = raw_edid + (i * EDID_LENGTH);
+   for (i = 1; i <= edid->extensions; i++) {
+   const u8 *ext = (const u8 *)edid + (i * EDID_LENGTH);
 
switch (*ext) {
case CEA_EXT:
@@ -2425,7 +2424,7 @@ drm_monitor_supports_rb(struct edid *edid)
if (edid->revision >= 4) {
bool ret = false;
 
-   drm_for_each_detailed_block((u8 *)edid, is_rb, &ret);
+   drm_for_each_detailed_block(edid, is_rb, &ret);
return ret;
}
 
@@ -2452,7 +2451,7 @@ drm_gtf2_hbreak(struct edid *edid)
 {
const struct detailed_timing *timing = NULL;
 
-   drm_for_each_detailed_block((u8 *)edid, find_gtf2, &timing);
+   drm_for_each_detailed_block(edid, find_gtf2, &timing);
 
BUILD_BUG_ON(offsetof(typeof(*timing), 
data.other_data.data.range.formula.gtf2.hfreq_start_khz) != 12);
 
@@ -2464,7 +2463,7 @@ drm_gtf2_2c(struct edid *edid)
 {
const struct detailed_timing *timing = NULL;
 
-   drm_for_each_detailed_block((u8 *)edid, find_gtf2, &timing);
+   drm_for_each_detailed_block(edid, find_gtf2, &timing);
 
BUILD_BUG_ON(offsetof(typeof(*timing), 
data.other_data.data.range.formula.gtf2.c) != 13);
 
@@ -2476,7 +2475,7 @@ drm_gtf2_m(struct edid *edid)
 {
const struct detailed_timing *timing = NULL;
 
-   drm_for_each_detailed_block((u8 *)edid, find_gtf2, &timing);
+   drm_for_each_detailed_block(edid, find_gtf2, &timing);
 
BUILD_BUG_ON(offsetof(typeof(*timing), 
data.other_data.data.range.formula.gtf2.m) != 14);
 
@@ -2488,7 +2487,7 @@ drm_gtf2_k(struct edid *edid)
 {
const struct detailed_timing *timing = NULL;
 
-   drm_for_each_detailed_block((u8 *)edid, find_gtf2, &timing);
+   drm_for_each_detailed_block(edid, find_gtf2, &timing);
 
BUILD_BUG_ON(offsetof(typeof(*timing), 
data.other_data.data.range.formula.gtf2.k) != 16);
 
@@ -2500,7 +2499,7 @@ drm_gtf2_2j(struct edid *edid)
 {
const struct detailed_timing *timing = NULL;
 
-   drm_for_each_detailed_block((u8 *)edid, find_gtf2, &timing);
+   drm_for_each_detailed_block(edid, find_gtf2, &timing);
 
BUILD_BUG_ON(offsetof(typeof(*timing), 
data.other_data.data.range.formula.gtf2.j) != 17);
 
@@ -3050,8 +3049,7 @@ add_inferred_modes(struct drm_connector *connector, 
struct edid *edid)
};
 
if (version_greater(edid, 1, 0))
-   drm_for_each_detailed_block((u8 *)edid, do_inferred_modes,
-   &closure);
+   drm_for_each_detailed_block(edid, do_inferred_modes, &closure);
 
return closure.modes;
 }
@@ -3130,8 +

[PATCH 9/9] drm/edid: add more general struct edid constness in the interfaces

2022-03-25 Thread Jani Nikula
With this, the remaining non-const parts are the ones that actually
modify the EDID, for example to fix corrupt EDID.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 
---
 drivers/gpu/drm/drm_edid.c | 21 +++--
 include/drm/drm_edid.h | 10 +-
 2 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index fae6f39897c8..a069c2ddb09d 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2150,7 +2150,7 @@ static u32 edid_extract_panel_id(const struct edid *edid)
 
 u32 drm_edid_get_panel_id(struct i2c_adapter *adapter)
 {
-   struct edid *edid;
+   const struct edid *edid;
u32 panel_id;
 
edid = drm_do_get_edid_base_block(NULL, drm_do_probe_ddc_edid, adapter);
@@ -3659,7 +3659,7 @@ static bool drm_valid_hdmi_vic(u8 vic)
 }
 
 static int
-add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
+add_alternate_cea_modes(struct drm_connector *connector, const struct edid 
*edid)
 {
struct drm_device *dev = connector->dev;
struct drm_display_mode *mode, *tmp;
@@ -4340,7 +4340,7 @@ static void drm_parse_y420cmdb_bitmap(struct 
drm_connector *connector,
 }
 
 static int
-add_cea_modes(struct drm_connector *connector, struct edid *edid)
+add_cea_modes(struct drm_connector *connector, const struct edid *edid)
 {
const u8 *cea = drm_find_cea_extension(edid);
const u8 *db, *hdmi = NULL, *video = NULL;
@@ -4546,7 +4546,7 @@ static int get_monitor_name(const struct edid *edid, char 
name[13])
  * @bufsize: The size of the name buffer (should be at least 14 chars.)
  *
  */
-void drm_edid_get_monitor_name(struct edid *edid, char *name, int bufsize)
+void drm_edid_get_monitor_name(const struct edid *edid, char *name, int 
bufsize)
 {
int name_length;
char buf[13];
@@ -4580,7 +4580,8 @@ static void clear_eld(struct drm_connector *connector)
  * Fill the ELD (EDID-Like Data) buffer for passing to the audio driver. The
  * HDCP and Port_ID ELD fields are left for the graphics driver to fill in.
  */
-static void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
+static void drm_edid_to_eld(struct drm_connector *connector,
+   const struct edid *edid)
 {
uint8_t *eld = connector->eld;
const u8 *cea;
@@ -4676,7 +4677,7 @@ static void drm_edid_to_eld(struct drm_connector 
*connector, struct edid *edid)
  *
  * Return: The number of found SADs or negative number on error.
  */
-int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads)
+int drm_edid_to_sad(const struct edid *edid, struct cea_sad **sads)
 {
int count = 0;
int i, start, end, dbl;
@@ -4738,7 +4739,7 @@ EXPORT_SYMBOL(drm_edid_to_sad);
  * Return: The number of found Speaker Allocation Blocks or negative number on
  * error.
  */
-int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb)
+int drm_edid_to_speaker_allocation(const struct edid *edid, u8 **sadb)
 {
int count = 0;
int i, start, end, dbl;
@@ -4833,7 +4834,7 @@ EXPORT_SYMBOL(drm_av_sync_delay);
  *
  * Return: True if the monitor is HDMI, false if not or unknown.
  */
-bool drm_detect_hdmi_monitor(struct edid *edid)
+bool drm_detect_hdmi_monitor(const struct edid *edid)
 {
const u8 *edid_ext;
int i;
@@ -4871,7 +4872,7 @@ EXPORT_SYMBOL(drm_detect_hdmi_monitor);
  *
  * Return: True if the monitor supports audio, false otherwise.
  */
-bool drm_detect_monitor_audio(struct edid *edid)
+bool drm_detect_monitor_audio(const struct edid *edid)
 {
const u8 *edid_ext;
int i, j;
@@ -5538,7 +5539,7 @@ static int add_displayid_detailed_1_modes(struct 
drm_connector *connector,
 }
 
 static int add_displayid_detailed_modes(struct drm_connector *connector,
-   struct edid *edid)
+   const struct edid *edid)
 {
const struct displayid_block *block;
struct displayid_iter iter;
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 144c495b99c4..48b1bf9c315a 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -372,8 +372,8 @@ struct drm_connector;
 struct drm_connector_state;
 struct drm_display_mode;
 
-int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads);
-int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb);
+int drm_edid_to_sad(const struct edid *edid, struct cea_sad **sads);
+int drm_edid_to_speaker_allocation(const struct edid *edid, u8 **sadb);
 int drm_av_sync_delay(struct drm_connector *connector,
  const struct drm_display_mode *mode);
 
@@ -569,8 +569,8 @@ int drm_add_edid_modes(struct drm_connector *connector, 
struct edid *edid);
 int drm_add_override_edid_modes(struct drm_connector *connector);
 
 u8 drm_match_cea_mode(const struct drm_display_mode *to_match);
-bool drm_detect_hdmi_monitor(struct edid *edid);
-bool drm_detect_mo

[PATCH v2 0/4] drm/atomic: Atomic Private State debugging

2022-03-25 Thread Maxime Ripard
Hi,

This series adds an atomic_print_state hook for drm_private_obj to ease the
debugging of driver-specific sub-classes, and adds one for vc4.

It also changes the call site of drm_atomic_print_new_state to make it more
consistent.

Let me know what you think,
Maxime

Changes from v1:
  - Added Daniel tags
  - Added drm_private_state documentation
  - Fixed unused variable warning
  - Removed the drm_atomic_nonblocking_commit() logging

Maxime Ripard (4):
  drm/atomic: Print the state every commit
  drm/atomic: Add atomic_print_state to private objects
  drm/vc4: Constify private state accessors
  drm/vc4: Implement atomic_print_state for HVS channel state

 drivers/gpu/drm/drm_atomic.c  | 20 
 drivers/gpu/drm/drm_atomic_uapi.c |  4 
 drivers/gpu/drm/vc4/vc4_kms.c | 24 +---
 include/drm/drm_atomic.h  | 27 +++
 4 files changed, 64 insertions(+), 11 deletions(-)

-- 
2.35.1



[PATCH v2 4/4] drm/vc4: Implement atomic_print_state for HVS channel state

2022-03-25 Thread Maxime Ripard
The HVS state configuration is useful when debugging what's going on in
the vc4 hardware pipeline. Add an implementation of .atomic_print_state.

Acked-by: Daniel Vetter 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/vc4/vc4_kms.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 26b771c919b1..bffd81d4bfcf 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -701,9 +701,26 @@ static void vc4_hvs_channels_destroy_state(struct 
drm_private_obj *obj,
kfree(hvs_state);
 }
 
+static void vc4_hvs_channels_print_state(struct drm_printer *p,
+const struct drm_private_state *state)
+{
+   struct vc4_hvs_state *hvs_state = to_vc4_hvs_state(state);
+   unsigned int i;
+
+   drm_printf(p, "HVS State\n");
+   drm_printf(p, "\tCore Clock Rate: %lu\n", hvs_state->core_clock_rate);
+
+   for (i = 0; i < HVS_NUM_CHANNELS; i++) {
+   drm_printf(p, "\tChannel %d\n", i);
+   drm_printf(p, "\t\tin use=%d\n", 
hvs_state->fifo_state[i].in_use);
+   drm_printf(p, "\t\tload=%lu\n", 
hvs_state->fifo_state[i].fifo_load);
+   }
+}
+
 static const struct drm_private_state_funcs vc4_hvs_state_funcs = {
.atomic_duplicate_state = vc4_hvs_channels_duplicate_state,
.atomic_destroy_state = vc4_hvs_channels_destroy_state,
+   .atomic_print_state = vc4_hvs_channels_print_state,
 };
 
 static void vc4_hvs_channels_obj_fini(struct drm_device *dev, void *unused)
-- 
2.35.1



[PATCH v2 3/4] drm/vc4: Constify private state accessors

2022-03-25 Thread Maxime Ripard
None of those helpers modify the pointed data, let's make them const.

Acked-by: Daniel Vetter 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/vc4/vc4_kms.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 24de29bc1cda..26b771c919b1 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -32,7 +32,8 @@ struct vc4_ctm_state {
int fifo;
 };
 
-static struct vc4_ctm_state *to_vc4_ctm_state(struct drm_private_state *priv)
+static struct vc4_ctm_state *
+to_vc4_ctm_state(const struct drm_private_state *priv)
 {
return container_of(priv, struct vc4_ctm_state, base);
 }
@@ -49,7 +50,7 @@ struct vc4_hvs_state {
 };
 
 static struct vc4_hvs_state *
-to_vc4_hvs_state(struct drm_private_state *priv)
+to_vc4_hvs_state(const struct drm_private_state *priv)
 {
return container_of(priv, struct vc4_hvs_state, base);
 }
@@ -61,7 +62,7 @@ struct vc4_load_tracker_state {
 };
 
 static struct vc4_load_tracker_state *
-to_vc4_load_tracker_state(struct drm_private_state *priv)
+to_vc4_load_tracker_state(const struct drm_private_state *priv)
 {
return container_of(priv, struct vc4_load_tracker_state, base);
 }
-- 
2.35.1



Re: [PATCH 2/9] drm/edid: pass a timing pointer to is_display_descriptor()

2022-03-25 Thread Ville Syrjälä
On Fri, Mar 25, 2022 at 02:25:24PM +0200, Jani Nikula wrote:
> Use struct member access instead of direct offsets to avoid lots of
> casts all over the place.
> 
> Use BUILD_BUG_ON() for sanity check.
> 
> Cc: Ville Syrjälä 
> Signed-off-by: Jani Nikula 
> ---
>  drivers/gpu/drm/drm_edid.c | 26 +++---
>  1 file changed, 15 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 1b552fe54f38..48707eef1dc2 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -2331,10 +2331,14 @@ struct drm_display_mode *drm_mode_find_dmt(struct 
> drm_device *dev,
>  }
>  EXPORT_SYMBOL(drm_mode_find_dmt);
>  
> -static bool is_display_descriptor(const u8 d[18], u8 tag)
> +static bool is_display_descriptor(const struct detailed_timing *timing, u8 
> type)
>  {
> - return d[0] == 0x00 && d[1] == 0x00 &&
> - d[2] == 0x00 && d[3] == tag;
> + BUILD_BUG_ON(offsetof(typeof(*timing), pixel_clock) != 0);
> + BUILD_BUG_ON(offsetof(typeof(*timing), data.other_data.pad1) != 2);
> + BUILD_BUG_ON(offsetof(typeof(*timing), data.other_data.type) != 3);
> +
> + return timing->pixel_clock == 0 && timing->data.other_data.pad1 == 0 &&

This would probably be less confusing if we moved pixel_clock into
pixel_data and just had matching padding bytes/etc. in other_data.

The names of all structs are also rather weird. We should probably
change them to match the spec terminology a bit more closely:
18 byte descriptor,detailed timing descriptor,display descriptor.
But that's a separate topic.

> + timing->data.other_data.type == type;
>  }
>  
>  static bool is_detailed_timing_descriptor(const u8 d[18])
> @@ -2405,7 +2409,7 @@ is_rb(struct detailed_timing *t, void *data)
>  {
>   u8 *r = (u8 *)t;
>  
> - if (!is_display_descriptor(r, EDID_DETAIL_MONITOR_RANGE))
> + if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_RANGE))
>   return;
>  
>   if (r[15] & 0x10)
> @@ -2431,7 +2435,7 @@ find_gtf2(struct detailed_timing *t, void *data)
>  {
>   u8 *r = (u8 *)t;
>  
> - if (!is_display_descriptor(r, EDID_DETAIL_MONITOR_RANGE))
> + if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_RANGE))
>   return;
>  
>   if (r[10] == 0x02)
> @@ -2987,7 +2991,7 @@ do_inferred_modes(struct detailed_timing *timing, void 
> *c)
>   struct detailed_non_pixel *data = &timing->data.other_data;
>   struct detailed_data_monitor_range *range = &data->data.range;
>  
> - if (!is_display_descriptor((const u8 *)timing, 
> EDID_DETAIL_MONITOR_RANGE))
> + if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE))
>   return;
>  
>   closure->modes += drm_dmt_modes_for_range(closure->connector,
> @@ -3067,7 +3071,7 @@ do_established_modes(struct detailed_timing *timing, 
> void *c)
>  {
>   struct detailed_mode_closure *closure = c;
>  
> - if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_EST_TIMINGS))
> + if (!is_display_descriptor(timing, EDID_DETAIL_EST_TIMINGS))
>   return;
>  
>   closure->modes += drm_est3_modes(closure->connector, timing);
> @@ -3122,7 +3126,7 @@ do_standard_modes(struct detailed_timing *timing, void 
> *c)
>   struct edid *edid = closure->edid;
>   int i;
>  
> - if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_STD_MODES))
> + if (!is_display_descriptor(timing, EDID_DETAIL_STD_MODES))
>   return;
>  
>   for (i = 0; i < 6; i++) {
> @@ -3231,7 +3235,7 @@ do_cvt_mode(struct detailed_timing *timing, void *c)
>  {
>   struct detailed_mode_closure *closure = c;
>  
> - if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_CVT_3BYTE))
> + if (!is_display_descriptor(timing, EDID_DETAIL_CVT_3BYTE))
>   return;
>  
>   closure->modes += drm_cvt_modes(closure->connector, timing);
> @@ -4491,7 +4495,7 @@ drm_parse_hdmi_vsdb_audio(struct drm_connector 
> *connector, const u8 *db)
>  static void
>  monitor_name(struct detailed_timing *t, void *data)
>  {
> - if (!is_display_descriptor((const u8 *)t, EDID_DETAIL_MONITOR_NAME))
> + if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_NAME))
>   return;
>  
>   *(u8 **)data = t->data.other_data.data.str.str;
> @@ -5226,7 +5230,7 @@ void get_monitor_range(struct detailed_timing *timing,
>   const struct detailed_non_pixel *data = &timing->data.other_data;
>   const struct detailed_data_monitor_range *range = &data->data.range;
>  
> - if (!is_display_descriptor((const u8 *)timing, 
> EDID_DETAIL_MONITOR_RANGE))
> + if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE))
>   return;
>  
>   /*
> -- 
> 2.30.2

-- 
Ville Syrjälä
Intel


Re: [PATCH 1/2] dma-buf: add dma_fence_unwrap

2022-03-25 Thread Christian König

Am 25.03.22 um 11:17 schrieb Daniel Vetter:

On Fri, Mar 25, 2022 at 11:10:15AM +0100, Christian König wrote:

Am 25.03.22 um 11:07 schrieb Daniel Vetter:

On Fri, Mar 25, 2022 at 11:03:54AM +0100, Daniel Vetter wrote:

On Fri, Mar 11, 2022 at 12:02:43PM +0100, Christian König wrote:

Add a general purpose helper to deep dive into dma_fence_chain/dma_fence_array
structures and iterate over all the fences in them.

This is useful when we need to flatten out all fences in those structures.

Signed-off-by: Christian König 
---
   Documentation/driver-api/dma-buf.rst  |   6 +
   drivers/dma-buf/Makefile  |   1 +
   drivers/dma-buf/selftests.h   |   1 +
   drivers/dma-buf/st-dma-fence-unwrap.c | 279 ++
   include/linux/dma-fence-unwrap.h  |  99 +
   5 files changed, 386 insertions(+)
   create mode 100644 drivers/dma-buf/st-dma-fence-unwrap.c
   create mode 100644 include/linux/dma-fence-unwrap.h

diff --git a/Documentation/driver-api/dma-buf.rst 
b/Documentation/driver-api/dma-buf.rst
index 2cd7db82d9fe..7209500f08c8 100644
--- a/Documentation/driver-api/dma-buf.rst
+++ b/Documentation/driver-api/dma-buf.rst
@@ -194,6 +194,12 @@ DMA Fence Chain
   .. kernel-doc:: include/linux/dma-fence-chain.h
  :internal:
+DMA Fence unwrap
+
+
+.. kernel-doc:: include/linux/dma-fence-unwrap.h
+   :internal:

Ok I forgot one bikeshed: I'd just include this in dma-fence-chain.h and
maybe go with the dma_fence_chain_unwrap_ prefix for everything. That
makes it even more clearer that the two are meant to go together. Plus ofc
the link from struct dma_fence_chain to this iterator in the docs too.

Or I'm just not understanding why you made this a separate thing?

Well it should be used to unwrap dma_fence_array containers as well and I
don't really want to add a dependency between dma_fence_chain and
dma_fence_array.

I've spend quite some work to keep the two containers separated and also
describe the separate use cases for each.

I can of course add some kerneldoc to let the chain and array documentation
point to this one here.

Yeah I think as a general iterator they should be fine as a separate
thing. Also just realized that we'd need links from both array and chain
to this since it's for both.


Done.



The other thing I noticed is that we have dma_fence_chain_for_each()
already. Should we replace all users of that outside of dma-fence-chain.c
with this new thing, and move the chain specific iterator into
dma-fence-chain.c so that it's hidden and people don't make funny
accidents? Just for more safety in this maze, also ofc that's all
follow-up.


Uff, good question. There are some valid use cases for it I think.

Especially the timeline syncobj handling only want to work with chain 
structures and not with the eventually contained array.


It could just be that we might want to wrap those use cases into 
dma_fence_chain helpers.


Anyway, not stuff for drm-misc-next-fixes, but going to keep that in mind.

Christian.


-Daniel




Thanks,
Christian.


-Daniel


+
   DMA Fence uABI/Sync File
   
diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
index 511805dbeb75..4c9eb53ba3f8 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -12,6 +12,7 @@ dmabuf_selftests-y := \
selftest.o \
st-dma-fence.o \
st-dma-fence-chain.o \
+   st-dma-fence-unwrap.o \
st-dma-resv.o
   obj-$(CONFIG_DMABUF_SELFTESTS)   += dmabuf_selftests.o
diff --git a/drivers/dma-buf/selftests.h b/drivers/dma-buf/selftests.h
index 97d73aaa31da..851965867d9c 100644
--- a/drivers/dma-buf/selftests.h
+++ b/drivers/dma-buf/selftests.h
@@ -12,4 +12,5 @@
   selftest(sanitycheck, __sanitycheck__) /* keep first (igt selfcheck) */
   selftest(dma_fence, dma_fence)
   selftest(dma_fence_chain, dma_fence_chain)
+selftest(dma_fence_unwrap, dma_fence_unwrap)
   selftest(dma_resv, dma_resv)
diff --git a/drivers/dma-buf/st-dma-fence-unwrap.c 
b/drivers/dma-buf/st-dma-fence-unwrap.c
new file mode 100644
index ..d821faaebe93
--- /dev/null
+++ b/drivers/dma-buf/st-dma-fence-unwrap.c
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: MIT
+
+/*
+ * Copyright (C) 2022 Advanced Micro Devices, Inc.
+ */
+
+#include 
+#if 0
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#endif
+
+#include "selftest.h"
+
+#define CHAIN_SZ (4 << 10)
+
+static struct kmem_cache *slab_fences;

Your own slab feels a bit like overkill. kmalloc/kfree not good enough?


+
+static inline struct mock_fence {
+   struct dma_fence base;
+   spinlock_t lock;
+} *to_mock_fence(struct dma_fence *f) {
+   return container_of(f, struct mock_fence, base);
+}
+
+static const char *mock_name(struct dma_fence *f)
+{
+   return "mock";
+}
+
+static void mock_fence_release(struct dma_fence *f)
+{
+   kmem_cache_free(slab_fences, to_mock_fence(f));
+}
+
+static const struct dma_fence_ops mock_ops 

[PATCH v2 2/4] drm/atomic: Add atomic_print_state to private objects

2022-03-25 Thread Maxime Ripard
A number of drivers (amdgpu, komeda, vc4, etc.) leverage the
drm_private_state structure, but we don't have any infrastructure to
provide debugging like we do for the other components state. Let's add
an atomic_print_state hook to be consistent.

Reviewed-by: Daniel Vetter 
Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/drm_atomic.c | 16 
 include/drm/drm_atomic.h | 27 +++
 2 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 73865c147b4b..7a52a9f4f487 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -789,6 +789,8 @@ drm_atomic_private_obj_init(struct drm_device *dev,
obj->state = state;
obj->funcs = funcs;
list_add_tail(&obj->head, &dev->mode_config.privobj_list);
+
+   state->obj = obj;
 }
 EXPORT_SYMBOL(drm_atomic_private_obj_init);
 
@@ -1636,6 +1638,15 @@ int __drm_atomic_helper_set_config(struct drm_mode_set 
*set,
 }
 EXPORT_SYMBOL(__drm_atomic_helper_set_config);
 
+static void drm_atomic_private_obj_print_state(struct drm_printer *p,
+  const struct drm_private_state 
*state)
+{
+   struct drm_private_obj *obj = state->obj;
+
+   if (obj->funcs->atomic_print_state)
+   obj->funcs->atomic_print_state(p, state);
+}
+
 /**
  * drm_atomic_print_new_state - prints drm atomic state
  * @state: atomic configuration to check
@@ -1656,6 +1667,8 @@ void drm_atomic_print_new_state(const struct 
drm_atomic_state *state,
struct drm_crtc_state *crtc_state;
struct drm_connector *connector;
struct drm_connector_state *connector_state;
+   struct drm_private_obj *obj;
+   struct drm_private_state *obj_state;
int i;
 
if (!p) {
@@ -1673,6 +1686,9 @@ void drm_atomic_print_new_state(const struct 
drm_atomic_state *state,
 
for_each_new_connector_in_state(state, connector, connector_state, i)
drm_atomic_connector_print_state(p, connector_state);
+
+   for_each_new_private_obj_in_state(state, obj, obj_state, i)
+   drm_atomic_private_obj_print_state(p, obj_state);
 }
 EXPORT_SYMBOL(drm_atomic_print_new_state);
 
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 1701c2128a5c..025085df 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -227,6 +227,18 @@ struct drm_private_state_funcs {
 */
void (*atomic_destroy_state)(struct drm_private_obj *obj,
 struct drm_private_state *state);
+
+   /**
+* @atomic_print_state:
+*
+* If driver subclasses &struct drm_private_state, it should implement
+* this optional hook for printing additional driver specific state.
+*
+* Do not call this directly, use drm_atomic_private_obj_print_state()
+* instead.
+*/
+   void (*atomic_print_state)(struct drm_printer *p,
+  const struct drm_private_state *state);
 };
 
 /**
@@ -311,14 +323,21 @@ struct drm_private_obj {
 
 /**
  * struct drm_private_state - base struct for driver private object state
- * @state: backpointer to global drm_atomic_state
  *
- * Currently only contains a backpointer to the overall atomic update, but in
- * the future also might hold synchronization information similar to e.g.
- * &drm_crtc.commit.
+ * Currently only contains a backpointer to the overall atomic update,
+ * and the relevant private object but in the future also might hold
+ * synchronization information similar to e.g. &drm_crtc.commit.
  */
 struct drm_private_state {
+   /**
+* @state: backpointer to global drm_atomic_state
+*/
struct drm_atomic_state *state;
+
+   /**
+* @obj: backpointer to the private object
+*/
+   struct drm_private_obj *obj;
 };
 
 struct __drm_private_objs_state {
-- 
2.35.1



Re: [PATCH 1/9] drm/edid: don't modify EDID while parsing

2022-03-25 Thread Ville Syrjälä
On Fri, Mar 25, 2022 at 02:25:23PM +0200, Jani Nikula wrote:
> We'll want to keep the EDID immutable while parsing. Stop modifying the
> EDID because of the quirks.
> 
> In theory, this does have userspace implications, but the userspace is
> supposed to use the modes exposed via KMS API, not by parsing the EDID
> directly.
> 
> Cc: Ville Syrjälä 
> Signed-off-by: Jani Nikula 

Reviewed-by: Ville Syrjälä 

> ---
>  drivers/gpu/drm/drm_edid.c | 18 +-
>  1 file changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index cc7bd58369df..1b552fe54f38 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -2740,9 +2740,9 @@ static struct drm_display_mode 
> *drm_mode_detailed(struct drm_device *dev,
>   return NULL;
>  
>   if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH)
> - timing->pixel_clock = cpu_to_le16(1088);
> -
> - mode->clock = le16_to_cpu(timing->pixel_clock) * 10;
> + mode->clock = 1088 * 10;
> + else
> + mode->clock = le16_to_cpu(timing->pixel_clock) * 10;
>  
>   mode->hdisplay = hactive;
>   mode->hsync_start = mode->hdisplay + hsync_offset;
> @@ -2763,14 +2763,14 @@ static struct drm_display_mode 
> *drm_mode_detailed(struct drm_device *dev,
>   drm_mode_do_interlace_quirk(mode, pt);
>  
>   if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
> - pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | 
> DRM_EDID_PT_VSYNC_POSITIVE;
> + mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC;
> + } else {
> + mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
> + DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
> + mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
> + DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
>   }
>  
> - mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
> - DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
> - mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
> - DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
> -
>  set_size:
>   mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4;
>   mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 
> 8;
> -- 
> 2.30.2

-- 
Ville Syrjälä
Intel


Re: [PATCH v2 -next] drm/vc4: Fix build error when CONFIG_DRM_VC4=y && CONFIG_RASPBERRYPI_FIRMWARE=m

2022-03-25 Thread Maxime Ripard
Hi,

On Fri, Mar 25, 2022 at 10:18:31AM +0800, Zheng Bin wrote:
> If CONFIG_DRM_VC4=y, CONFIG_RASPBERRYPI_FIRMWARE=m, CONFIG_COMPILE_TEST=n,
> bulding fails:
> 
> drivers/gpu/drm/vc4/vc4_drv.o: In function `vc4_drm_bind':
> vc4_drv.c:(.text+0x320): undefined reference to `rpi_firmware_get'
> vc4_drv.c:(.text+0x320): relocation truncated to fit: R_AARCH64_CALL26 
> against undefined symbol `rpi_firmware_get'
> vc4_drv.c:(.text+0x34c): undefined reference to `rpi_firmware_property'
> vc4_drv.c:(.text+0x34c): relocation truncated to fit: R_AARCH64_CALL26 
> against undefined symbol `rpi_firmware_property'
> vc4_drv.c:(.text+0x354): undefined reference to `rpi_firmware_put'
> vc4_drv.c:(.text+0x354): relocation truncated to fit: R_AARCH64_CALL26 
> against undefined symbol `rpi_firmware_put'
> 
> Make DRM_VC4 depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST to fix this.
> 
> Fixes: c406ad5e4a85 ("drm/vc4: Notify the firmware when DRM is in charge")
> Reported-by: Hulk Robot 
> Signed-off-by: Zheng Bin 
> ---
> v2: follow Maxime's advise, add RASPBERRYPI_FIRMWARE as an additional depends
>  drivers/gpu/drm/vc4/Kconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig
> index de3424fed2fc..92d74ba7c449 100644
> --- a/drivers/gpu/drm/vc4/Kconfig
> +++ b/drivers/gpu/drm/vc4/Kconfig
> @@ -2,6 +2,7 @@
>  config DRM_VC4
>   tristate "Broadcom VC4 Graphics"
>   depends on ARCH_BCM || ARCH_BCM2835 || COMPILE_TEST
> + depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST

Why do we need the || COMPILE_TEST here?

The rpi_firmware_get, _property and _put functions aren't define if
RASPBERRYPI_FIRMWARE, so we need that dependency every time, even if
COMPILE_TEST is set?

Maxime


signature.asc
Description: PGP signature


Re: [PATCH 3/9] drm/edid: use struct detailed_timing member access in is_rb()

2022-03-25 Thread Ville Syrjälä
On Fri, Mar 25, 2022 at 02:25:25PM +0200, Jani Nikula wrote:
> Use struct detailed_timing member access instead of direct offsets to
> avoid casting.
> 
> Use BUILD_BUG_ON() for sanity check.
> 
> Cc: Ville Syrjälä 
> Signed-off-by: Jani Nikula 
> 
> ---
> 
> Note: Why can we use range.formula.cvt.flags directly in is_rb() while
> gtf2 functions check for range.flags == 0x02 first to ensure it's gtf2?

Looks to me like is_rb() is just borked.

Other weird stuff I just noticed is get_monitor_range() not doing
anything for flags!=0x1 cases. It also fails to handle the other
flags that were added to byte 4 in EDID 1.4.

> ---
>  drivers/gpu/drm/drm_edid.c | 12 +++-
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 48707eef1dc2..5396fa78e864 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -2405,15 +2405,17 @@ drm_for_each_detailed_block(u8 *raw_edid, detailed_cb 
> *cb, void *closure)
>  }
>  
>  static void
> -is_rb(struct detailed_timing *t, void *data)
> +is_rb(struct detailed_timing *timing, void *data)
>  {
> - u8 *r = (u8 *)t;
> + bool *res = data;
>  
> - if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_RANGE))
> + if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE))

Calling this 'timing' when it's not is a bit confusing. I'd probably
rename it to something else for all the display descriptor cases.

>   return;
>  
> - if (r[15] & 0x10)
> - *(bool *)data = true;
> + BUILD_BUG_ON(offsetof(typeof(*timing), 
> data.other_data.data.range.formula.cvt.flags) != 15);
> +
> + if (timing->data.other_data.data.range.formula.cvt.flags & 0x10)
> + *res = true;
>  }
>  
>  /* EDID 1.4 defines this explicitly.  For EDID 1.3, we guess, badly. */
> -- 
> 2.30.2

-- 
Ville Syrjälä
Intel


Re: [PATCH v2 3/25] drm/amdgpu: Disable ABM when AC mode

2022-03-25 Thread Alex Deucher
On Fri, Mar 25, 2022 at 2:27 AM Ryan Lin  wrote:
>
> Disable ABM feature when the system is running on AC mode to get
> the more perfect contrast of the display.
>
> Signed-off-by: Ryan Lin 
>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c  |  4 ++
>  drivers/gpu/drm/amd/amdgpu/amdgpu_device.c|  1 +
>  drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c | 58 ---
>  drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h   |  1 +
>  4 files changed, 42 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> index c560c1ab62ecb..bc8bb9aad2e36 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> @@ -822,6 +822,10 @@ static int amdgpu_acpi_event(struct notifier_block *nb,
> struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, 
> acpi_nb);
> struct acpi_bus_event *entry = (struct acpi_bus_event *)data;
>
> +   if (strcmp(entry->device_class, "battery") == 0) {
> +   adev->pm.ac_power = power_supply_is_system_supplied() > 0;
> +   }
> +

We already set adev->pm.ac_power in amdgpu_pm_acpi_event_handler()
which gets called a few lines below.

Alex


> if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) {
> if (power_supply_is_system_supplied() > 0)
> DRM_DEBUG_DRIVER("pm: AC\n");
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index abfcc1304ba0c..3a0afe7602727 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -3454,6 +3454,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
>
> adev->gfx.gfx_off_req_count = 1;
> adev->pm.ac_power = power_supply_is_system_supplied() > 0;
> +   adev->pm.old_ac_power = true;
>
> atomic_set(&adev->throttling_logging_enabled, 1);
> /*
> diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c 
> b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
> index 54a1408c8015c..478a734b66926 100644
> --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
> +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
> @@ -23,6 +23,8 @@
>   *
>   */
>
> +#include 
> +#include "amdgpu.h"
>  #include "dmub_abm.h"
>  #include "dce_abm.h"
>  #include "dc.h"
> @@ -51,6 +53,7 @@
>  #define DISABLE_ABM_IMMEDIATELY 255
>
>
> +extern uint amdgpu_dm_abm_level;
>
>  static void dmub_abm_enable_fractional_pwm(struct dc_context *dc)
>  {
> @@ -117,28 +120,6 @@ static void dmub_abm_init(struct abm *abm, uint32_t 
> backlight)
> dmub_abm_enable_fractional_pwm(abm->ctx);
>  }
>
> -static unsigned int dmub_abm_get_current_backlight(struct abm *abm)
> -{
> -   struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
> -   unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL);
> -
> -   /* return backlight in hardware format which is unsigned 17 bits, with
> -* 1 bit integer and 16 bit fractional
> -*/
> -   return backlight;
> -}
> -
> -static unsigned int dmub_abm_get_target_backlight(struct abm *abm)
> -{
> -   struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
> -   unsigned int backlight = REG_READ(BL1_PWM_TARGET_ABM_LEVEL);
> -
> -   /* return backlight in hardware format which is unsigned 17 bits, with
> -* 1 bit integer and 16 bit fractional
> -*/
> -   return backlight;
> -}
> -
>  static bool dmub_abm_set_level(struct abm *abm, uint32_t level)
>  {
> union dmub_rb_cmd cmd;
> @@ -148,6 +129,9 @@ static bool dmub_abm_set_level(struct abm *abm, uint32_t 
> level)
> int edp_num;
> uint8_t panel_mask = 0;
>
> +   if (power_supply_is_system_supplied() > 0)
> +   level = 0;
> +
> get_edp_links(dc->dc, edp_links, &edp_num);
>
> for (i = 0; i < edp_num; i++) {
> @@ -170,6 +154,36 @@ static bool dmub_abm_set_level(struct abm *abm, uint32_t 
> level)
> return true;
>  }
>
> +static unsigned int dmub_abm_get_current_backlight(struct abm *abm)
> +{
> +   struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
> +   unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL);
> +   struct dc_context *dc = abm->ctx;
> +   struct amdgpu_device *adev = dc->driver_context;
> +
> +   if (adev->pm.ac_power != adev->pm.old_ac_power) {
> +   dmub_abm_set_level(abm, amdgpu_dm_abm_level);
> +   adev->pm.ac_power = power_supply_is_system_supplied() > 0;
> +   adev->pm.old_ac_power = adev->pm.ac_power;
> +   }
> +
> +   /* return backlight in hardware format which is unsigned 17 bits, with
> +* 1 bit integer and 16 bit fractional
> +*/
> +   return backlight;
> +}
> +
> +static unsigned int dmub_abm_get_target_backlight(struct abm *abm)
> +{
> +   struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
> +   unsigned int backlight = REG_READ(BL1_PWM_TARG

RE: [PATCH v5 3/9] arm64: dts: qcom: sc7280: Enable backlight for eDP panel

2022-03-25 Thread Sankeerth Billakanti (QUIC)


> -Original Message-
> From: Stephen Boyd 
> Sent: Friday, March 18, 2022 2:58 AM
> To: Sankeerth Billakanti (QUIC) ;
> devicet...@vger.kernel.org; dri-devel@lists.freedesktop.org;
> freedr...@lists.freedesktop.org; linux-arm-...@vger.kernel.org; linux-
> ker...@vger.kernel.org
> Cc: robdcl...@gmail.com; seanp...@chromium.org; quic_kalyant
> ; Abhinav Kumar (QUIC)
> ; diand...@chromium.org; Kuogee Hsieh
> (QUIC) ; agr...@kernel.org;
> bjorn.anders...@linaro.org; robh...@kernel.org; krzk...@kernel.org;
> s...@poorly.run; airl...@linux.ie; dan...@ffwll.ch;
> thierry.red...@gmail.com; s...@ravnborg.org;
> dmitry.barysh...@linaro.org; quic_vproddut 
> Subject: Re: [PATCH v5 3/9] arm64: dts: qcom: sc7280: Enable backlight for
> eDP panel
> 
> Quoting Sankeerth Billakanti (2022-03-16 10:35:48)
> > Enable backlight support for eDP panel on CRD platform for sc7280.
> >
> > Signed-off-by: Sankeerth Billakanti 
> > ---
> >
> > Changes in v5:
> >   - Separate out backlight nodes
> >
> >  arch/arm64/boot/dts/qcom/sc7280-crd.dts | 18 ++
> >  1 file changed, 18 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/qcom/sc7280-crd.dts
> > b/arch/arm64/boot/dts/qcom/sc7280-crd.dts
> > index 2df654e..16d1a5b 100644
> > --- a/arch/arm64/boot/dts/qcom/sc7280-crd.dts
> > +++ b/arch/arm64/boot/dts/qcom/sc7280-crd.dts
> > @@ -37,6 +37,15 @@
> > pinctrl-0 = <&edp_panel_power>;
> > };
> >
> > +   edp_backlight: edp-backlight {
> 
> Does this also move to qcard.dtsi? Why can't this be combined with the
> previous patch?
> 
The nodes related to pwm are dependent on
https://patchwork.kernel.org/project/linux-arm-msm/list/?series=620127&state=*

We moved them to different patch so that the other patch can be merged without 
depending on above series. I will rearrange to get backlight definitions also 
here.

> > +   compatible = "pwm-backlight";
> > +
> > +   power-supply = <&vreg_edp_bp>;
> > +   pwms = <&pm8350c_pwm 3 65535>;
> > +
> > +   enable-gpios = <&pm8350c_gpios 7 GPIO_ACTIVE_HIGH>;
> > +   };
> > +
> > vreg_edp_bp: vreg-edp-bp-regulator {
> > compatible = "regulator-fixed";
> > regulator-name = "vreg_edp_bp"; @@ -123,7 +132,9 @@
> > ap_ts_pen_1v8: &i2c13 {
> > edp_panel: edp-panel {
> > compatible = "edp-panel";
> >
> > +   backlight = <&edp_backlight>;
> > power-supply = <&edp_3v3_regulator>;
> > +
> 
> Nitpick: Remove this newline from this hunk and put it in when power-supply
> is introduced.
> 

Okay, will make that change.

> > ports {
> > #address-cells = <1>;
> > #size-cells = <0>; @@ -172,6 +183,13
> > @@ ap_ts_pen_1v8: &i2c13 {
> > };
> >  };
> >
> > +&pm8350c_pwm {
> > +   status = "okay";
> > +
> > +   pinctrl-names = "default";
> > +   pinctrl-0 = <&edp_bl_pwm>;
> 
> I see the pinctrl is used now but it would be easier to review this patch if 
> the
> pinctrl was in this patch.

Okay. I will rearrange the hunks from this and the previous patch.


RE: [PATCH v5 2/9] arm64: dts: qcom: sc7280: Add support for eDP panel on CRD

2022-03-25 Thread Sankeerth Billakanti (QUIC)


> -Original Message-
> From: Doug Anderson 
> Sent: Friday, March 18, 2022 10:51 PM
> To: Sankeerth Billakanti (QUIC) 
> Cc: dri-devel ; linux-arm-msm  m...@vger.kernel.org>; freedreno ;
> LKML ; open list:OPEN FIRMWARE AND
> FLATTENED DEVICE TREE BINDINGS ; Rob Clark
> ; Sean Paul ; Stephen
> Boyd ; quic_kalyant ;
> Abhinav Kumar (QUIC) ; Kuogee Hsieh (QUIC)
> ; Andy Gross ;
> bjorn.anders...@linaro.org; Rob Herring ;
> krzk...@kernel.org; Sean Paul ; David Airlie
> ; Daniel Vetter ; Thierry Reding
> ; Sam Ravnborg ;
> dmitry.barysh...@linaro.org; quic_vproddut 
> Subject: Re: [PATCH v5 2/9] arm64: dts: qcom: sc7280: Add support for eDP
> panel on CRD
> 
> Hi,
> 
> On Wed, Mar 16, 2022 at 10:36 AM Sankeerth Billakanti
>  wrote:
> >
> > Enable support for eDP interface via aux_bus on CRD platform.
> >
> > Signed-off-by: Sankeerth Billakanti 
> > ---
> >
> > Changes in v5:
> >   - Change the order of patches
> >   - Remove the backlight nodes
> >   - Remove the bias setting
> >   - Fix compilation issue
> >   - Model VREG_EDP_BP for backlight power
> >
> > Changes in v4:
> >   - Create new patch for name changes
> >   - Remove output-low
> >
> > Changes in v3:
> >   - Sort the nodes alphabetically
> >   - Use - instead of _ as node names
> >   - Place the backlight and panel nodes under root
> >   - Change the name of edp_out to mdss_edp_out
> >   - Change the names of regulator nodes
> >   - Delete unused properties in the board file
> >
> >
> > Changes in v2:
> >   - Sort node references alphabetically
> >   - Improve readability
> >   - Move the pwm pinctrl to pwm node
> >   - Move the regulators to root
> >   - Define backlight power
> >   - Remove dummy regulator node
> >   - Cleanup pinctrl definitions
> >
> >  arch/arm64/boot/dts/qcom/sc7280-crd.dts | 93
> > +
> >  1 file changed, 93 insertions(+)
> 
> At a high level, I'd expect your patch to be based upon Matthias's series, AKA
> the 4 patches from:
> 
> https://lore.kernel.org/r/20220316172814.v1.1.I2deda8f2cd6adfbb525a97d8f
> ee008a8477b7b0e@changeid/
> 
> I'll leave it up to you about whether you care to support eDP on the old
> CRD1/2 or just on CRD3. Personally I'd think CRD3 would be enough.
> 
> Then, I'd expect your patch to mostly incorporate
> , though that patch was written before aux-
> bus support so the panel would need to go in a different place.
> 
> Stephen already gave some comments and basing on Matthias's patches will
> be a pretty big change, so I probably won't comment lots more.
> 
> 

I rebased my change on top of Matthias's changes now. We are discussing about 
the qcard changes internally to understand the way ahead.
I believe all my current changes are localized to the crd-r3 files only for the 
qyalcomm crd3.1

I want to have a different series for c and dt changes to expedite review 
process. May I separate the c changes from this series?

> > +&mdss_edp {
> > +   status = "okay";
> > +
> > +   data-lanes = <0 1 2 3>;
> > +   vdda-1p2-supply = <&vreg_l6b_1p2>;
> > +   vdda-0p9-supply = <&vreg_l10c_0p8>;
> > +
> > +   aux-bus {
> > +   edp_panel: edp-panel {
> 
> As Stephen pointed out, it should be called "panel".

Okay. Will make that change


Re: [PATCH v5 2/9] arm64: dts: qcom: sc7280: Add support for eDP panel on CRD

2022-03-25 Thread Doug Anderson
Hi,

On Fri, Mar 25, 2022 at 6:41 AM Sankeerth Billakanti (QUIC)
 wrote:
>
> > -Original Message-
> > From: Doug Anderson 
> > Sent: Friday, March 18, 2022 10:51 PM
> > To: Sankeerth Billakanti (QUIC) 
> > Cc: dri-devel ; linux-arm-msm  > m...@vger.kernel.org>; freedreno ;
> > LKML ; open list:OPEN FIRMWARE AND
> > FLATTENED DEVICE TREE BINDINGS ; Rob Clark
> > ; Sean Paul ; Stephen
> > Boyd ; quic_kalyant ;
> > Abhinav Kumar (QUIC) ; Kuogee Hsieh (QUIC)
> > ; Andy Gross ;
> > bjorn.anders...@linaro.org; Rob Herring ;
> > krzk...@kernel.org; Sean Paul ; David Airlie
> > ; Daniel Vetter ; Thierry Reding
> > ; Sam Ravnborg ;
> > dmitry.barysh...@linaro.org; quic_vproddut 
> > Subject: Re: [PATCH v5 2/9] arm64: dts: qcom: sc7280: Add support for eDP
> > panel on CRD
> >
> > Hi,
> >
> > On Wed, Mar 16, 2022 at 10:36 AM Sankeerth Billakanti
> >  wrote:
> > >
> > > Enable support for eDP interface via aux_bus on CRD platform.
> > >
> > > Signed-off-by: Sankeerth Billakanti 
> > > ---
> > >
> > > Changes in v5:
> > >   - Change the order of patches
> > >   - Remove the backlight nodes
> > >   - Remove the bias setting
> > >   - Fix compilation issue
> > >   - Model VREG_EDP_BP for backlight power
> > >
> > > Changes in v4:
> > >   - Create new patch for name changes
> > >   - Remove output-low
> > >
> > > Changes in v3:
> > >   - Sort the nodes alphabetically
> > >   - Use - instead of _ as node names
> > >   - Place the backlight and panel nodes under root
> > >   - Change the name of edp_out to mdss_edp_out
> > >   - Change the names of regulator nodes
> > >   - Delete unused properties in the board file
> > >
> > >
> > > Changes in v2:
> > >   - Sort node references alphabetically
> > >   - Improve readability
> > >   - Move the pwm pinctrl to pwm node
> > >   - Move the regulators to root
> > >   - Define backlight power
> > >   - Remove dummy regulator node
> > >   - Cleanup pinctrl definitions
> > >
> > >  arch/arm64/boot/dts/qcom/sc7280-crd.dts | 93
> > > +
> > >  1 file changed, 93 insertions(+)
> >
> > At a high level, I'd expect your patch to be based upon Matthias's series, 
> > AKA
> > the 4 patches from:
> >
> > https://lore.kernel.org/r/20220316172814.v1.1.I2deda8f2cd6adfbb525a97d8f
> > ee008a8477b7b0e@changeid/
> >
> > I'll leave it up to you about whether you care to support eDP on the old
> > CRD1/2 or just on CRD3. Personally I'd think CRD3 would be enough.
> >
> > Then, I'd expect your patch to mostly incorporate
> > , though that patch was written before aux-
> > bus support so the panel would need to go in a different place.
> >
> > Stephen already gave some comments and basing on Matthias's patches will
> > be a pretty big change, so I probably won't comment lots more.
> >
> >
>
> I rebased my change on top of Matthias's changes now. We are discussing about 
> the qcard changes internally to understand the way ahead.
> I believe all my current changes are localized to the crd-r3 files only for 
> the qyalcomm crd3.1
>
> I want to have a different series for c and dt changes to expedite review 
> process. May I separate the c changes from this series?

I'd have no problems with that. They go into different trees and if it
makes it easier to get a new version of the driver out while you're
figuring out what to do about the dts then I'd say let's do it.

-Doug


Re: Parallel modesets and private state objects broken, where to go with MST?

2022-03-25 Thread Maxime Ripard
Hi Lyude,

On Mon, Mar 14, 2022 at 06:16:36PM -0400, Lyude Paul wrote:
> Hi! First a little bit of background: I've recently been trying to get rid of
> all of the non-atomic payload bandwidth management code in the MST helpers in
> order to make it easier to implement DSC and fallback link rate retraining
> support down the line. Currently bandwidth information is stored in two
> places, partially in the MST atomic state and partially in the mst manager's
> payload table (which exists outside of the atomic state and has its own
> locking). The portions in the atomic state are used to try to determine if a
> given display configuration can fit within the given bandwidth limitations
> during the atomic check phase, and are implemented through the use of private
> state objects.

Yeah, this looks awfully similar to what vc4 is doing.

The way the hardware is setup is that there's a device (HVS) that does
the composition of all planes, over 3 FIFO, and each FIFO can be output
to a CRTC with a mux. The HVS then needs to raise its internal clock
rate depending on the load (based on the resolution and number of
planes, mostly) of each FIFO.

Thus we have a private object (vc4_hvs_state) that lists all the FIFOs,
with their associated loads, and we pull that state in for each commit.

> My current goal has been to move as much of this as possible over to the
> atomic state and entirely get rid of the payload table along with it's locks.
> My main reason for doing this is that it both decomplicates things quite a
> bit, and I'm really also hoping that getting rid of that payload code will
> make it clearer to others how it works - and stop the influx of bandaid
> patches (e.g. adding more and more special cases to MST to fix poorly
> understood issues being hit in one specific driver and nowhere else) that I've
> had to spend way more time then I'd like trying to investigate and review.
> 
> So, the actual problem: following a conversation with Daniel Vetter today I've
> gotten the impression that private modesetting objects are basically just
> broken with parallel modesets? I'm still wrapping my head around all of this
> honestly, but from what I've gathered: CRTC atomic infra knows how to do waits
> in the proper places for when other CRTCs need to be waited on to continue a
> modeset, but there's no such tracking with private objects. If I understand
> this correctly, that means that even if two CRTC modesets require pulling in
> the same private object state for the MST mgr: we're only provided a guarantee
> that the atomic checks pulling in that private object state won't
> concurrently. But when it comes to commits, it doesn't sound like there's any
> actual tracking for this and as such - two CRTC modesets which have both
> pulled in the MST private state object are not prevented from running
> concurrently.

Yeah, in our case the issue was two-fold:

 - The first one is that since the load is shared over each CRTC, we
   need, for each commit, to have the global load. This is non-obvious
   because you might get some new states that only affect a single CRTC,
   or a plane but not its CRTC, so making sure we always get the entire
   picture was a bit challenging.

   You'll need to pull the state at each commit in atomic_check, and
   then basically remove the old state of whatever is in your commit,
   and add the new stuff. Just iterating over all the connectors in a
   state for example won't work.


 - Then, indeed, there's a race issue. IIRC, the basic idea is that if
   two (non-blocking) commits don't share any resources (so like both
   have a single plane, CRTC and connector, but none shared), there's no
   execution ordering guaranteed by default. But there is one in the
   structures: you still have your old and new states.

   So if you commit your changes like this:

   * Initial State
   * State 1
   * State 2

   Your old private object in state 1 will be the initial state one, the
   new will be the one from state 1. And for state 2, the old will be
   state 1, the new will be state 2.

   But if state 2 gets committed first, then your old state is weird
   already, because it's actually the next one. It get worse when state
   1 gets committed since the old state is the initial state, but since
   state 2 has been committed the initial state has been freed already.

> This unfortunately throws an enormous wrench into the MST atomic conversion
> I've been working on - as I was under the understanding while writing the code
> for this that all objects in an atomic state are blocked from being used in
> any new atomic commits (not checks, as parallel checks should be fine in my
> case) until there's no commits active with said object pulled into the atomic
> state. I certainly am not aware of any way parallel modesetting could actually
> be supported on MST, so it's not really a feature we want to deal with at all
> besides stopping it from happening. This also unfortunately means that the
>

RE: [PATCH v5 2/9] arm64: dts: qcom: sc7280: Add support for eDP panel on CRD

2022-03-25 Thread Sankeerth Billakanti (QUIC)


> -Original Message-
> From: Stephen Boyd 
> Sent: Friday, March 18, 2022 2:53 AM
> To: Sankeerth Billakanti (QUIC) ;
> devicet...@vger.kernel.org; dri-devel@lists.freedesktop.org;
> freedr...@lists.freedesktop.org; linux-arm-...@vger.kernel.org; linux-
> ker...@vger.kernel.org
> Cc: robdcl...@gmail.com; seanp...@chromium.org; quic_kalyant
> ; Abhinav Kumar (QUIC)
> ; diand...@chromium.org; Kuogee Hsieh
> (QUIC) ; agr...@kernel.org;
> bjorn.anders...@linaro.org; robh...@kernel.org; krzk...@kernel.org;
> s...@poorly.run; airl...@linux.ie; dan...@ffwll.ch;
> thierry.red...@gmail.com; s...@ravnborg.org;
> dmitry.barysh...@linaro.org; quic_vproddut 
> Subject: Re: [PATCH v5 2/9] arm64: dts: qcom: sc7280: Add support for eDP
> panel on CRD
> 
> Quoting Sankeerth Billakanti (2022-03-16 10:35:47)
> > diff --git a/arch/arm64/boot/dts/qcom/sc7280-crd.dts
> > b/arch/arm64/boot/dts/qcom/sc7280-crd.dts
> > index e2efbdd..2df654e 100644
> > --- a/arch/arm64/boot/dts/qcom/sc7280-crd.dts
> > +++ b/arch/arm64/boot/dts/qcom/sc7280-crd.dts
> > @@ -7,6 +7,7 @@
> >
> >  /dts-v1/;
> >
> > +#include 
> >  #include "sc7280-idp.dtsi"
> >  #include "sc7280-idp-ec-h1.dtsi"
> >
> > @@ -21,6 +22,27 @@
> > chosen {
> > stdout-path = "serial0:115200n8";
> > };
> > +
> > +   edp_3v3_regulator: edp-3v3-regulator {
> > +   compatible = "regulator-fixed";
> > +   regulator-name = "edp_3v3_regulator";
> > +
> > +   regulator-min-microvolt = <330>;
> > +   regulator-max-microvolt = <330>;
> > +
> > +   gpio = <&tlmm 80 GPIO_ACTIVE_HIGH>;
> > +   enable-active-high;
> > +
> > +   pinctrl-names = "default";
> > +   pinctrl-0 = <&edp_panel_power>;
> > +   };
> > +
> > +   vreg_edp_bp: vreg-edp-bp-regulator {
> > +   compatible = "regulator-fixed";
> > +   regulator-name = "vreg_edp_bp";
> > +   regulator-always-on;
> > +   regulator-boot-on;
> > +   };
> >  };
> >
> >  &apps_rsc {
> > @@ -76,6 +98,58 @@ ap_ts_pen_1v8: &i2c13 {
> > };
> >  };
> >
> > +&mdss {
> > +   status = "okay";
> > +};
> > +
> > +&mdss_dp {
> > +   status = "okay";
> > +
> > +   pinctrl-names = "default";
> > +   pinctrl-0 = <&dp_hot_plug_det>;
> > +   data-lanes = <0 1>;
> > +   vdda-1p2-supply = <&vreg_l6b_1p2>;
> > +   vdda-0p9-supply = <&vreg_l1b_0p8>; };
> > +
> > +&mdss_edp {
> > +   status = "okay";
> > +
> > +   data-lanes = <0 1 2 3>;
> 
> Is this property necessary? It looks like the default.
> 

Will remove it

> > +   vdda-1p2-supply = <&vreg_l6b_1p2>;
> > +   vdda-0p9-supply = <&vreg_l10c_0p8>;
> > +
> > +   aux-bus {
> 
> Can this move to sc7280.dtsi and get a phandle?
>

Okay, I will move this to sc7280.dtsi like below.
Shall I define the required properties under &mdss_edp_panel node in the 
sc7280-crd3.dts?

--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
@@ -3283,6 +3283,18 @@

status = "disabled";

+   aux-bus {
+   mdss_edp_panel: panel {
+   compatible = "edp-panel";
+
+   port {
+   mdss_edp_panel_in: 
endpoint {
+   remote-endpoint 
= <&mdss_edp_out>;
+   };
+   };
+   };
+   };
+
ports {
#address-cells = <1>;
#size-cells = <0>;
@@ -3296,7 +3308,9 @@

port@1 {
reg = <1>;
-   mdss_edp_out: endpoint { };
+   mdss_edp_out: endpoint {
+   remote-endpoint = 
<&mdss_edp_panel_in>;
+   };
};
};
 
> > +   edp_panel: edp-panel {
> 
> I'd prefer
> 
>   edp_panel: panel {
> 
> because there's only one panel node at this level.
> 

Okay. I will change it.

> > +   compatible = "edp-panel";
> > +
> > +   power-supply = <&edp_3v3_regulator>;
> 
> This is board specific, but I thought it was on the qcard so we should move
> this to sc7280-qcard.dtsi?
> 

Qcard is used only for herobrine as of now according to the code. We defined 
this only for CRD. We will discuss this internally to understand the plan ahead.

> > + 

[PATCH v2 1/4] drm/atomic: Print the state every commit

2022-03-25 Thread Maxime Ripard
The DRM_UT_STATE controls whether we're calling
drm_atomic_print_new_state() whenever a new state is committed. However,
that call is made in the drm_mode_atomic_ioctl(), whereas we have
multiple users of the drm_atomic_commit() function in the kernel
(framebuffer emulation, drm_atomic_helper_dirtyfb, etc.). Similarly,
it's only called for a blocking atomic commit.

This leads to multiple states being committed but never actually
displayed even though we asked to have verbose atomic state debugging.

Let's move the call to drm_atomic_print_new_state() to
drm_atomic_commit() to make sure we don't miss any.

Signed-off-by: Maxime Ripard 
---
 drivers/gpu/drm/drm_atomic.c  | 4 
 drivers/gpu/drm/drm_atomic_uapi.c | 4 
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 88cd992df356..73865c147b4b 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1423,6 +1423,7 @@ EXPORT_SYMBOL(drm_atomic_check_only);
 int drm_atomic_commit(struct drm_atomic_state *state)
 {
struct drm_mode_config *config = &state->dev->mode_config;
+   struct drm_printer p = drm_info_printer(state->dev->dev);
int ret;
 
ret = drm_atomic_check_only(state);
@@ -1431,6 +1432,9 @@ int drm_atomic_commit(struct drm_atomic_state *state)
 
drm_dbg_atomic(state->dev, "committing %p\n", state);
 
+   if (drm_debug_enabled(DRM_UT_STATE))
+   drm_atomic_print_new_state(state, &p);
+
return config->funcs->atomic_commit(state->dev, state, false);
 }
 EXPORT_SYMBOL(drm_atomic_commit);
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index 9781722519c3..45e6d3c62a9a 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -1326,7 +1326,6 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
struct drm_out_fence_state *fence_state;
int ret = 0;
unsigned int i, j, num_fences;
-   struct drm_printer p = drm_info_printer(dev->dev);
 
/* disallow for drivers not supporting atomic: */
if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
@@ -1458,9 +1457,6 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
ret = drm_atomic_nonblocking_commit(state);
} else {
-   if (drm_debug_enabled(DRM_UT_STATE))
-   drm_atomic_print_new_state(state, &p);
-
ret = drm_atomic_commit(state);
}
 
-- 
2.35.1



RE: [PATCH v5 5/9] drm/msm/dp: Add eDP support via aux_bus

2022-03-25 Thread Sankeerth Billakanti (QUIC)


> -Original Message-
> From: Stephen Boyd 
> Sent: Friday, March 18, 2022 3:08 AM
> To: Sankeerth Billakanti (QUIC) ;
> devicet...@vger.kernel.org; dri-devel@lists.freedesktop.org;
> freedr...@lists.freedesktop.org; linux-arm-...@vger.kernel.org; linux-
> ker...@vger.kernel.org
> Cc: robdcl...@gmail.com; seanp...@chromium.org; quic_kalyant
> ; Abhinav Kumar (QUIC)
> ; diand...@chromium.org; Kuogee Hsieh
> (QUIC) ; agr...@kernel.org;
> bjorn.anders...@linaro.org; robh...@kernel.org; krzk...@kernel.org;
> s...@poorly.run; airl...@linux.ie; dan...@ffwll.ch;
> thierry.red...@gmail.com; s...@ravnborg.org;
> dmitry.barysh...@linaro.org; quic_vproddut 
> Subject: Re: [PATCH v5 5/9] drm/msm/dp: Add eDP support via aux_bus
> 
> Quoting Sankeerth Billakanti (2022-03-16 10:35:50)
> > This patch adds support for generic eDP sink through aux_bus.
> 
> Please unindent commit text paragraphs. This isn't a book.
> 

Okay. Will change it.

> > The eDP/DP controller driver should support aux transactions
> > originating from the panel-edp driver and hence should be initialized and
> ready.
> >
> > The panel bridge supporting the panel should be ready before
> > the bridge connector is initialized. The generic panel probe needs the
> > controller resources to be enabled to support aux tractions
> > originating
> 
> s/tractions/transactions/
>

Will correct it
 
> > from it. So, the host_init and phy_init are moved to execute before
> > the panel probe.
> >
> > The host_init has to return early if the core is already
> > initialized so that the regulator and clock votes for the controller
> > resources are balanced.
> >
> > EV_HPD_INIT_SETUP needs to execute immediately to enable the
> > interrupts for the aux transactions from panel-edp to get the modes
> > supported.
> 
> There are a lot of things going on in this patch. Can it be split up?
>

I can split them up.

> >
> > Signed-off-by: Sankeerth Billakanti 
> > ---
> >  drivers/gpu/drm/msm/dp/dp_display.c | 65
> +++--
> >  drivers/gpu/drm/msm/dp/dp_drm.c | 10 +++---
> >  drivers/gpu/drm/msm/dp/dp_parser.c  | 21 +---
> > drivers/gpu/drm/msm/dp/dp_parser.h  |  1 +
> >  4 files changed, 70 insertions(+), 27 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
> > b/drivers/gpu/drm/msm/dp/dp_display.c
> > index 382b3aa..688bbed 100644
> > --- a/drivers/gpu/drm/msm/dp/dp_display.c
> > +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> > @@ -10,6 +10,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >
> >  #include "msm_drv.h"
> >  #include "msm_kms.h"
> > @@ -265,8 +266,6 @@ static int dp_display_bind(struct device *dev, struct
> device *master,
> > goto end;
> > }
> >
> > -   dp->dp_display.next_bridge = dp->parser->next_bridge;
> > -
> > dp->aux->drm_dev = drm;
> > rc = dp_aux_register(dp->aux);
> > if (rc) {
> > @@ -421,6 +420,11 @@ static void dp_display_host_init(struct
> dp_display_private *dp)
> > dp->dp_display.connector_type, dp->core_initialized,
> > dp->phy_initialized);
> >
> > +   if (dp->core_initialized) {
> > +   DRM_DEBUG_DP("DP core already initialized\n");
> > +   return;
> > +   }
> > +
> > dp_power_init(dp->power, false);
> > dp_ctrl_reset_irq_ctrl(dp->ctrl, true);
> > dp_aux_init(dp->aux);
> > @@ -433,6 +437,11 @@ static void dp_display_host_deinit(struct
> dp_display_private *dp)
> > dp->dp_display.connector_type, dp->core_initialized,
> > dp->phy_initialized);
> >
> > +   if (!dp->core_initialized) {
> > +   DRM_DEBUG_DP("DP core not initialized\n");
> > +   return;
> > +   }
> > +
> > dp_ctrl_reset_irq_ctrl(dp->ctrl, false);
> > dp_aux_deinit(dp->aux);
> > dp_power_deinit(dp->power);
> > @@ -1502,7 +1511,7 @@ void msm_dp_irq_postinstall(struct msm_dp
> > *dp_display)
> >
> > dp_hpd_event_setup(dp);
> >
> > -   dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 100);
> > +   dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 0);
> >  }
> >
> >  void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor
> > *minor) @@ -1524,6 +1533,52 @@ void msm_dp_debugfs_init(struct
> msm_dp *dp_display, struct drm_minor *minor)
> > }
> >  }
> >
> > +static int dp_display_get_next_bridge(struct msm_dp *dp) {
> > +   int rc = 0;
> 
> Drop initialization.
> 

Okay.

> > +   struct dp_display_private *dp_priv;
> > +   struct device_node *aux_bus;
> > +   struct device *dev;
> > +
> > +   dp_priv = container_of(dp, struct dp_display_private, dp_display);
> > +   dev = &dp_priv->pdev->dev;
> > +   aux_bus = of_get_child_by_name(dev->of_node, "aux-bus");
> > +
> > +   if (aux_bus) {
> > +   dp_display_host_init(dp_priv);
> > +   dp_catalog_ctrl_hpd_config(dp_priv->catalog);

Re: [git pull] drm fixes for 5.18-rc1

2022-03-25 Thread Thomas Zimmermann

Hi

Am 25.03.22 um 03:13 schrieb Dave Airlie:

Hi Linus,

Some fixes were queued up in and in light of the fbdev regressions,
I've pulled those in as well,
I think the mediatek one is going to be a bit more painful, since now
you have a merge and I need to have the mediatek stuff get rebased and
retested onto that merge point, but I'll make sure they get to you
ASAP.

Thomas, cc'ed, I pulled your fbdev fixes from patchwork, since they
were a clear regression fix, don't bother queueing them up in our
trees now.


I added them to drm-misc-next a while ago, but I guess they missed our 
-rc6 deadline. Thanks for taking care.


Best regards
Thomas



Dave.

drm-next-2022-03-25:
drm fixes for 5.18-rc1

core:
- Make audio and color plane support checking only happen
   when a CEA extension block is found.
- Small selftest fix.

fbdev:
- two regressions fixes from speedup patches.

ttm:
- Fix a small regression from ttm_resource_fini()

i915:
- Reject unsupported TMDS rates on ICL+
- Treat SAGV block time 0 as SAGV disabled
- Fix PSF GV point mask when SAGV is not possible
- Fix renamed INTEL_INFO->media.arch/ver field
The following changes since commit c6e90a1c660874736bd09c1fec6312b4b4c2ff7b:

   Merge tag 'amd-drm-next-5.18-2022-03-18' of
https://gitlab.freedesktop.org/agd5f/linux into drm-next (2022-03-21
13:48:20 +1000)

are available in the Git repository at:

   git://anongit.freedesktop.org/drm/drm tags/drm-next-2022-03-25

for you to fetch changes up to 2a81dba4b577099717cea86d429f053e85e74d96:

   fbdev: Fix cfb_imageblit() for arbitrary image widths (2022-03-25
09:55:54 +1000)


drm fixes for 5.18-rc1

core:
- Make audio and color plane support checking only happen
   when a CEA extension block is found.
- Small selftest fix.

fbdev:
- two regressions fixes from speedup patches.

ttm:
- Fix a small regression from ttm_resource_fini()

i915:
- Reject unsupported TMDS rates on ICL+
- Treat SAGV block time 0 as SAGV disabled
- Fix PSF GV point mask when SAGV is not possible
- Fix renamed INTEL_INFO->media.arch/ver field


Cooper Chiou (1):
   drm/edid: check basic audio support on CEA extension block

Dave Airlie (2):
   Merge tag 'drm-intel-next-fixes-2022-03-24' of
git://anongit.freedesktop.org/drm/drm-intel into drm-next
   Merge tag 'drm-misc-next-fixes-2022-03-24-1' of
git://anongit.freedesktop.org/drm/drm-misc into drm-next

Jani Nikula (1):
   drm/edid: fix CEA extension byte #3 parsing

Lucas De Marchi (1):
   drm/i915: Fix renamed struct field

Nathan Chancellor (1):
   drm/selftest: plane_helper: Put test structures in static storage

Thomas Zimmermann (2):
   fbdev: Fix sys_imageblit() for arbitrary image widths
   fbdev: Fix cfb_imageblit() for arbitrary image widths

Ville Syrjälä (3):
   drm/i915: Reject unsupported TMDS rates on ICL+
   drm/i915: Treat SAGV block time 0 as SAGV disabled
   drm/i915: Fix PSF GV point mask when SAGV is not possible

Zack Rusin (1):
   drm/ttm: Fix a kernel oops due to an invalid read

  drivers/gpu/drm/drm_edid.c| 15 
  drivers/gpu/drm/i915/display/intel_bw.c   |  3 ++-
  drivers/gpu/drm/i915/display/intel_hdmi.c |  9 +++
  drivers/gpu/drm/i915/i915_drv.h   |  2 +-
  drivers/gpu/drm/i915/intel_pm.c   | 10 
  drivers/gpu/drm/selftests/test-drm_plane_helper.c |  8 +++
  drivers/gpu/drm/ttm/ttm_range_manager.c   |  2 +-
  drivers/video/fbdev/core/cfbimgblt.c  | 28 ++
  drivers/video/fbdev/core/sysimgblt.c  | 29 +++
  9 files changed, 82 insertions(+), 24 deletions(-)


--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev


OpenPGP_signature
Description: OpenPGP digital signature


Re: [PATCH v2 3/25] drm/amdgpu: Disable ABM when AC mode

2022-03-25 Thread Harry Wentland



On 2022-03-25 00:05, Ryan Lin wrote:
> Disable ABM feature when the system is running on AC mode to get
> the more perfect contrast of the display.

It says patch 3 out of 25. Are there other patches? If so, I can't
find them in my mailbox and neither can patchwork
https://patchwork.freedesktop.org/series/101767/
 
> Signed-off-by: Ryan Lin 
> 
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c  |  4 ++
>  drivers/gpu/drm/amd/amdgpu/amdgpu_device.c|  1 +
>  drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c | 58 ---
>  drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h   |  1 +
>  4 files changed, 42 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> index c560c1ab62ecb..bc8bb9aad2e36 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> @@ -822,6 +822,10 @@ static int amdgpu_acpi_event(struct notifier_block *nb,
>   struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, 
> acpi_nb);
>   struct acpi_bus_event *entry = (struct acpi_bus_event *)data;
>  
> + if (strcmp(entry->device_class, "battery") == 0) {
> + adev->pm.ac_power = power_supply_is_system_supplied() > 0;
> + }
> +
>   if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) {
>   if (power_supply_is_system_supplied() > 0)
>   DRM_DEBUG_DRIVER("pm: AC\n");
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index abfcc1304ba0c..3a0afe7602727 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -3454,6 +3454,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
>  
>   adev->gfx.gfx_off_req_count = 1;
>   adev->pm.ac_power = power_supply_is_system_supplied() > 0;
> + adev->pm.old_ac_power = true;
>  
>   atomic_set(&adev->throttling_logging_enabled, 1);
>   /*
> diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c 
> b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
> index 54a1408c8015c..478a734b66926 100644
> --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
> +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
> @@ -23,6 +23,8 @@
>   *
>   */
>  
> +#include 
> +#include "amdgpu.h"
>  #include "dmub_abm.h"
>  #include "dce_abm.h"
>  #include "dc.h"
> @@ -51,6 +53,7 @@
>  #define DISABLE_ABM_IMMEDIATELY 255
>  
>  
> +extern uint amdgpu_dm_abm_level;
>  
>  static void dmub_abm_enable_fractional_pwm(struct dc_context *dc)
>  {
> @@ -117,28 +120,6 @@ static void dmub_abm_init(struct abm *abm, uint32_t 
> backlight)
>   dmub_abm_enable_fractional_pwm(abm->ctx);
>  }
>  
> -static unsigned int dmub_abm_get_current_backlight(struct abm *abm)
> -{
> - struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
> - unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL);
> -
> - /* return backlight in hardware format which is unsigned 17 bits, with
> -  * 1 bit integer and 16 bit fractional
> -  */
> - return backlight;
> -}
> -
> -static unsigned int dmub_abm_get_target_backlight(struct abm *abm)
> -{
> - struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
> - unsigned int backlight = REG_READ(BL1_PWM_TARGET_ABM_LEVEL);
> -
> - /* return backlight in hardware format which is unsigned 17 bits, with
> -  * 1 bit integer and 16 bit fractional
> -  */
> - return backlight;
> -}
> -
>  static bool dmub_abm_set_level(struct abm *abm, uint32_t level)
>  {
>   union dmub_rb_cmd cmd;
> @@ -148,6 +129,9 @@ static bool dmub_abm_set_level(struct abm *abm, uint32_t 
> level)
>   int edp_num;
>   uint8_t panel_mask = 0;
>  
> + if (power_supply_is_system_supplied() > 0)
> + level = 0;
> +
>   get_edp_links(dc->dc, edp_links, &edp_num);
>  
>   for (i = 0; i < edp_num; i++) {
> @@ -170,6 +154,36 @@ static bool dmub_abm_set_level(struct abm *abm, uint32_t 
> level)
>   return true;
>  }
>  
> +static unsigned int dmub_abm_get_current_backlight(struct abm *abm)
> +{
> + struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
> + unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL);
> + struct dc_context *dc = abm->ctx;
> + struct amdgpu_device *adev = dc->driver_context;
> +
> + if (adev->pm.ac_power != adev->pm.old_ac_power) {

This file lives in DC, which is shared code between Windows and Linux. We
cannot directly use adev here. Any information needs to go through DC structs.

I seem to remember someone saying that ABM gets disabled on Windows when
we're in AC mode. Have you checked with our Windows guys about this? I feel
we're re-inventing the wheel here for no good reason.

Harry

> + dmub_abm_set_level(abm, amdgpu_dm_abm_level);
> + adev->pm.ac_power = power_supply_is_system_supplied() > 0;
> + adev->pm.old_ac_power = adev->pm.ac_power;
> + }
> +
> + /* return b

Re: [PATCH] drm/amd: Re-classify some log messages in commit path

2022-03-25 Thread Harry Wentland
On 2022-03-24 20:06, Sean Paul wrote:
> From: Sean Paul 
> 
> ATOMIC and DRIVER log categories do not typically contain per-frame log
> messages. This patch re-classifies some messages in amd to chattier
> categories to keep ATOMIC/DRIVER quiet.
> 
> Signed-off-by: Sean Paul 

With the subject line fixed as per Christian's comment this is
Reviewed-by: Harry Wentland 

Harry

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_display.c   | 5 +++--
>  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 
>  2 files changed, 7 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
> index fae5c1debfad..1fcbab2fd3c3 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
> @@ -113,8 +113,9 @@ static void amdgpu_display_flip_work_func(struct 
> work_struct *__work)
>   spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
>  
>  
> - DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_SUBMITTED, work: 
> %p,\n",
> -  amdgpu_crtc->crtc_id, amdgpu_crtc, 
> work);
> + drm_dbg_vbl(adev_to_drm(adev),
> + "crtc:%d[%p], pflip_stat:AMDGPU_FLIP_SUBMITTED, work: 
> %p,\n",
> + amdgpu_crtc->crtc_id, amdgpu_crtc, work);
>  
>  }
>  
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index b30656959fd8..45d130f86114 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -9248,7 +9248,7 @@ static void amdgpu_dm_commit_planes(struct 
> drm_atomic_state *state,
>   &bundle->flip_addrs[planes_count].address,
>   afb->tmz_surface, false);
>  
> - DRM_DEBUG_ATOMIC("plane: id=%d dcc_en=%d\n",
> + drm_dbg_state(state->dev, "plane: id=%d dcc_en=%d\n",
>new_plane_state->plane->index,
>bundle->plane_infos[planes_count].dcc.enable);
>  
> @@ -9282,7 +9282,7 @@ static void amdgpu_dm_commit_planes(struct 
> drm_atomic_state *state,
>   dc_plane,
>   
> bundle->flip_addrs[planes_count].flip_timestamp_in_us);
>  
> - DRM_DEBUG_ATOMIC("%s Flipping to hi: 0x%x, low: 0x%x\n",
> + drm_dbg_state(state->dev, "%s Flipping to hi: 0x%x, low: 
> 0x%x\n",
>__func__,
>
> bundle->flip_addrs[planes_count].address.grph.addr.high_part,
>
> bundle->flip_addrs[planes_count].address.grph.addr.low_part);
> @@ -9624,7 +9624,7 @@ static void amdgpu_dm_atomic_commit_tail(struct 
> drm_atomic_state *state)
>   dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
>   dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
>  
> - DRM_DEBUG_ATOMIC(
> + drm_dbg_state(state->dev,
>   "amdgpu_crtc id:%d crtc_state_flags: enable:%d, 
> active:%d, "
>   "planes_changed:%d, mode_changed:%d,active_changed:%d,"
>   "connectors_changed:%d\n",
> @@ -10328,7 +10328,7 @@ static int dm_update_crtc_state(struct 
> amdgpu_display_manager *dm,
>   if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
>   goto skip_modeset;
>  
> - DRM_DEBUG_ATOMIC(
> + drm_dbg_state(state->dev,
>   "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
>   "planes_changed:%d, mode_changed:%d,active_changed:%d,"
>   "connectors_changed:%d\n",



Re: [PATCH v6 0/6] drm: exynos: dsi: Convert drm bridge

2022-03-25 Thread Marek Szyprowski
Hi Jagan,

On 03.03.2022 17:36, Jagan Teki wrote:
> Updated series about drm bridge conversion of exynos dsi.
>
> Previous version can be accessible, here [1].
>
> Patch 1: tc358764 panel_bridge API
>
> Patch 2: connector reset
>
> Patch 3: bridge attach in MIC
>
> Patch 4: panel_bridge API
>
> Patch 5: bridge conversion
>
> Patch 6: atomic functions
>
>
>
> Any inputs?


I'm really sorry for the delay on my side. I was really busy with other 
things and I was not able to check the display of the boards with remote 
access.


Finally, this patchset works properly on all my Exynos-based test systems:

1. Exynos4210 Trats with Samsung s6e8aa0 DSI panel

2. Exynos4412 Trats2 with Samsung s6e8aa0 DSI panel

3. Exynos5250 Arndale with TC358764 DSI-LVDS bridge and LVDS panel

4. Exynos5433 TM2e with Samsung s6e3hf2 DSI panel and internal Exynos 
MIC bridge


I will post my acked-by and tested-by tags for each patch.


> Jagan.
>
> Jagan Teki (6):
>drm: bridge: tc358764: Use drm panel_bridge API
>drm: bridge: panel: Reset the connector state pointer
>exynos: drm: dsi: Attach in_bridge in MIC driver
>drm: exynos: dsi: Use drm panel_bridge API
>drm: exynos: dsi: Convert to bridge driver
>drm: exynos: dsi: Switch to atomic funcs
>
>   drivers/gpu/drm/bridge/panel.c  |   3 +
>   drivers/gpu/drm/bridge/tc358764.c   | 104 +-
>   drivers/gpu/drm/exynos/exynos_drm_dsi.c | 241 ++--
>   drivers/gpu/drm/exynos/exynos_drm_mic.c |  22 +++
>   4 files changed, 93 insertions(+), 277 deletions(-)
>
Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH v6 1/6] drm: bridge: tc358764: Use drm panel_bridge API

2022-03-25 Thread Marek Szyprowski


On 03.03.2022 17:36, Jagan Teki wrote:
> Replace the manual panel handling code by a drm panel_bridge via
> devm_drm_of_get_bridge().
>
> Adding panel_bridge handling,
>
> - Drops drm_connector and related operations as drm_bridge_attach
>creates connector during attachment.
>
> - Drops panel pointer and panel healpers.
>
> This simplifies the driver and allows all components in the display
> pipeline to be treated as bridges.
>
> Signed-off-by: Jagan Teki 

Acked-by: Marek Szyprowski 

Tested-by: Marek Szyprowski 

> ---
> Changes for v6:
> - none
> Changes for v2:
> - s/panel_bridge/next_bridge
> - drop unneeded headers
>
>   drivers/gpu/drm/bridge/tc358764.c | 104 ++
>   1 file changed, 6 insertions(+), 98 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/tc358764.c 
> b/drivers/gpu/drm/bridge/tc358764.c
> index c1e35bdf9232..dca41ed32f8a 100644
> --- a/drivers/gpu/drm/bridge/tc358764.c
> +++ b/drivers/gpu/drm/bridge/tc358764.c
> @@ -16,14 +16,9 @@
>   #include 
>   
>   #include 
> -#include 
> -#include 
> -#include 
>   #include 
>   #include 
> -#include 
>   #include 
> -#include 
>   
>   #define FLD_MASK(start, end)(((1 << ((start) - (end) + 1)) - 1) << 
> (end))
>   #define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
> @@ -153,10 +148,9 @@ static const char * const tc358764_supplies[] = {
>   struct tc358764 {
>   struct device *dev;
>   struct drm_bridge bridge;
> - struct drm_connector connector;
> + struct drm_bridge *next_bridge;
>   struct regulator_bulk_data supplies[ARRAY_SIZE(tc358764_supplies)];
>   struct gpio_desc *gpio_reset;
> - struct drm_panel *panel;
>   int error;
>   };
>   
> @@ -210,12 +204,6 @@ static inline struct tc358764 *bridge_to_tc358764(struct 
> drm_bridge *bridge)
>   return container_of(bridge, struct tc358764, bridge);
>   }
>   
> -static inline
> -struct tc358764 *connector_to_tc358764(struct drm_connector *connector)
> -{
> - return container_of(connector, struct tc358764, connector);
> -}
> -
>   static int tc358764_init(struct tc358764 *ctx)
>   {
>   u32 v = 0;
> @@ -278,43 +266,11 @@ static void tc358764_reset(struct tc358764 *ctx)
>   usleep_range(1000, 2000);
>   }
>   
> -static int tc358764_get_modes(struct drm_connector *connector)
> -{
> - struct tc358764 *ctx = connector_to_tc358764(connector);
> -
> - return drm_panel_get_modes(ctx->panel, connector);
> -}
> -
> -static const
> -struct drm_connector_helper_funcs tc358764_connector_helper_funcs = {
> - .get_modes = tc358764_get_modes,
> -};
> -
> -static const struct drm_connector_funcs tc358764_connector_funcs = {
> - .fill_modes = drm_helper_probe_single_connector_modes,
> - .destroy = drm_connector_cleanup,
> - .reset = drm_atomic_helper_connector_reset,
> - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> -};
> -
> -static void tc358764_disable(struct drm_bridge *bridge)
> -{
> - struct tc358764 *ctx = bridge_to_tc358764(bridge);
> - int ret = drm_panel_disable(bridge_to_tc358764(bridge)->panel);
> -
> - if (ret < 0)
> - dev_err(ctx->dev, "error disabling panel (%d)\n", ret);
> -}
> -
>   static void tc358764_post_disable(struct drm_bridge *bridge)
>   {
>   struct tc358764 *ctx = bridge_to_tc358764(bridge);
>   int ret;
>   
> - ret = drm_panel_unprepare(ctx->panel);
> - if (ret < 0)
> - dev_err(ctx->dev, "error unpreparing panel (%d)\n", ret);
>   tc358764_reset(ctx);
>   usleep_range(1, 15000);
>   ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
> @@ -335,72 +291,25 @@ static void tc358764_pre_enable(struct drm_bridge 
> *bridge)
>   ret = tc358764_init(ctx);
>   if (ret < 0)
>   dev_err(ctx->dev, "error initializing bridge (%d)\n", ret);
> - ret = drm_panel_prepare(ctx->panel);
> - if (ret < 0)
> - dev_err(ctx->dev, "error preparing panel (%d)\n", ret);
> -}
> -
> -static void tc358764_enable(struct drm_bridge *bridge)
> -{
> - struct tc358764 *ctx = bridge_to_tc358764(bridge);
> - int ret = drm_panel_enable(ctx->panel);
> -
> - if (ret < 0)
> - dev_err(ctx->dev, "error enabling panel (%d)\n", ret);
>   }
>   
>   static int tc358764_attach(struct drm_bridge *bridge,
>  enum drm_bridge_attach_flags flags)
> -{
> - struct tc358764 *ctx = bridge_to_tc358764(bridge);
> - struct drm_device *drm = bridge->dev;
> - int ret;
> -
> - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
> - DRM_ERROR("Fix bridge driver to make connector optional!");
> - return -EINVAL;
> - }
> -
> - ctx->connector.polled = DRM_CONNECTOR_POLL_HPD;
> - ret = drm_connector_init(drm, &ctx->connector,
> -  &tc358764_connector_funcs,
> -

Re: [PATCH v6 2/6] drm: bridge: panel: Reset the connector state pointer

2022-03-25 Thread Marek Szyprowski


On 03.03.2022 17:36, Jagan Teki wrote:
> Trigger hotplug event with drm_kms_helper_hotplug_event might fail if the
> connector state pointer is NULL.
>
> BUG observed in exynos dsi driver where drm_bridge_attach is trying to 
> register
> a connector in panel_bridge before the hotplug event is triggered,
>
> WARNING: CPU: 1 PID: 1 at drivers/gpu/drm/drm_atomic_state_helper.c:494 
> drm_atomic_helper_connector_duplicate_state+0x94/0x9c
> Modules linked in:
> CPU: 1 PID: 1 Comm: swapper/0 Tainted: G W 5.16.0-rc1-9-g704b1dbfa4c2 
> #11058
> Hardware name: Samsung Exynos (Flattened Device Tree)
> [] (unwind_backtrace) from [] (show_stack+0x10/0x14)
> [] (show_stack) from [] (dump_stack_lvl+0x58/0x70)
> [] (dump_stack_lvl) from [] (__warn+0xd0/0x134)
> [] (__warn) from [] (warn_slowpath_fmt+0x5c/0xb4)
> [] (warn_slowpath_fmt) from [] 
> (drm_atomic_helper_connector_duplicate_state+0x94/0x9c)
> [] (drm_atomic_helper_connector_duplicate_state) from [] 
> (drm_atomic_get_connector_state+0xd4/0x190)
> [] (drm_atomic_get_connector_state) from [] 
> (__drm_atomic_helper_set_config+0x314/0x368)
> [] (__drm_atomic_helper_set_config) from [] 
> (drm_client_modeset_commit_atomic+0x170/0x278)
> [] (drm_client_modeset_commit_atomic) from [] 
> (drm_client_modeset_commit_locked+0x60/0x1c8)
> [] (drm_client_modeset_commit_locked) from [] 
> (drm_client_modeset_commit+0x24/0x40)
> [] (drm_client_modeset_commit) from [] 
> (drm_fb_helper_set_par+0xb8/0xf8)
> [] (drm_fb_helper_set_par) from [] 
> (fbcon_init+0x2c0/0x518)
> [] (fbcon_init) from [] (visual_init+0xc0/0x108)
> [] (visual_init) from [] (do_bind_con_driver+0x1b8/0x3a4)
> [] (do_bind_con_driver) from [] 
> (do_take_over_console+0x13c/0x1e8)
> [] (do_take_over_console) from [] 
> (do_fbcon_takeover+0x78/0xd8)
> [] (do_fbcon_takeover) from [] 
> (register_framebuffer+0x208/0x2e0)
> [] (register_framebuffer) from [] 
> (__drm_fb_helper_initial_config_and_unlock+0x400/0x63c)
> [] (__drm_fb_helper_initial_config_and_unlock) from [] 
> (drm_kms_helper_hotplug_event+0x24/0x30)
> [] (drm_kms_helper_hotplug_event) from [] 
> (exynos_dsi_host_attach+0x174/0x1fc)
> [] (exynos_dsi_host_attach) from [] 
> (s6e8aa0_probe+0x1b4/0x218)
>
> So reset the atomic state for a given connector by freeing the state pointer
> and allocate a new empty state object. This can be done using connector
> funcs->reset helper and has to be done before the hotplug even calls.
>
> This patch calls the connector->funcs->reset in panel_bridge_attach.
>
> Signed-off-by: Jagan Teki 

Acked-by: Marek Szyprowski 

Tested-by: Marek Szyprowski 

> ---
> Changes for v6, v5:
> - none
> Changes for v4:
> - new patch
>
>   drivers/gpu/drm/bridge/panel.c | 3 +++
>   1 file changed, 3 insertions(+)
>
> diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
> index b32295abd9e7..f6eea194482a 100644
> --- a/drivers/gpu/drm/bridge/panel.c
> +++ b/drivers/gpu/drm/bridge/panel.c
> @@ -83,6 +83,9 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
>   drm_connector_attach_encoder(&panel_bridge->connector,
> bridge->encoder);
>   
> + if (connector->funcs->reset)
> + connector->funcs->reset(connector);
> +
>   return 0;
>   }
>   

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH v6 3/6] exynos: drm: dsi: Attach in_bridge in MIC driver

2022-03-25 Thread Marek Szyprowski


On 03.03.2022 17:36, Jagan Teki wrote:
> MIC drivers in the Exynos5433 display pipeline are already registered
> as bridge drivers and it is more advisable to attach the downstream
> bridge on the bridge attach call instead of doing the same in the
> DSI driver.
>
> This makes bridge attachment more meaningful and avoids the races
> during bridge function calls.
>
> So, move the bridge finding and drm_bridge_attach from DSI to MIC.
>
> Signed-off-by: Jagan Teki 

Acked-by: Marek Szyprowski 

Tested-by: Marek Szyprowski 

> ---
> Changes for v6:
> - new patch
>
>   drivers/gpu/drm/exynos/exynos_drm_dsi.c | 15 ---
>   drivers/gpu/drm/exynos/exynos_drm_mic.c | 22 ++
>   2 files changed, 22 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
> b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index b7d0a4aead0a..741c046513e8 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -1660,11 +1660,6 @@ static int exynos_dsi_of_read_u32(const struct 
> device_node *np,
>   return ret;
>   }
>   
> -enum {
> - DSI_PORT_IN,
> - DSI_PORT_OUT
> -};
> -
>   static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)
>   {
>   struct device *dev = dsi->dev;
> @@ -1695,8 +1690,6 @@ static int exynos_dsi_bind(struct device *dev, struct 
> device *master,
>   struct exynos_dsi *dsi = dev_get_drvdata(dev);
>   struct drm_encoder *encoder = &dsi->encoder;
>   struct drm_device *drm_dev = data;
> - struct device_node *in_bridge_node;
> - struct drm_bridge *in_bridge;
>   int ret;
>   
>   drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
> @@ -1707,14 +1700,6 @@ static int exynos_dsi_bind(struct device *dev, struct 
> device *master,
>   if (ret < 0)
>   return ret;
>   
> - in_bridge_node = of_graph_get_remote_node(dev->of_node, DSI_PORT_IN, 0);
> - if (in_bridge_node) {
> - in_bridge = of_drm_find_bridge(in_bridge_node);
> - if (in_bridge)
> - drm_bridge_attach(encoder, in_bridge, NULL, 0);
> - of_node_put(in_bridge_node);
> - }
> -
>   return mipi_dsi_host_register(&dsi->dsi_host);
>   }
>   
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c 
> b/drivers/gpu/drm/exynos/exynos_drm_mic.c
> index 32672bf8ae4a..9e06f8e2a863 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
> @@ -102,6 +102,7 @@ struct exynos_mic {
>   struct videomode vm;
>   struct drm_encoder *encoder;
>   struct drm_bridge bridge;
> + struct drm_bridge *next_bridge;
>   
>   bool enabled;
>   };
> @@ -298,12 +299,22 @@ static void mic_pre_enable(struct drm_bridge *bridge)
>   
>   static void mic_enable(struct drm_bridge *bridge) { }
>   
> +static int mic_attach(struct drm_bridge *bridge,
> +   enum drm_bridge_attach_flags flags)
> +{
> + struct exynos_mic *mic = bridge->driver_private;
> +
> + return drm_bridge_attach(bridge->encoder, mic->next_bridge,
> +  &mic->bridge, flags);
> +}
> +
>   static const struct drm_bridge_funcs mic_bridge_funcs = {
>   .disable = mic_disable,
>   .post_disable = mic_post_disable,
>   .mode_set = mic_mode_set,
>   .pre_enable = mic_pre_enable,
>   .enable = mic_enable,
> + .attach = mic_attach,
>   };
>   
>   static int exynos_mic_bind(struct device *dev, struct device *master,
> @@ -377,6 +388,7 @@ static int exynos_mic_probe(struct platform_device *pdev)
>   {
>   struct device *dev = &pdev->dev;
>   struct exynos_mic *mic;
> + struct device_node *remote;
>   struct resource res;
>   int ret, i;
>   
> @@ -420,6 +432,16 @@ static int exynos_mic_probe(struct platform_device *pdev)
>   }
>   }
>   
> + remote = of_graph_get_remote_node(dev->of_node, 1, 0);
> + mic->next_bridge = of_drm_find_bridge(remote);
> + if (IS_ERR(mic->next_bridge)) {
> + DRM_DEV_ERROR(dev, "mic: Failed to find next bridge\n");
> + ret = PTR_ERR(mic->next_bridge);
> + goto err;
> + }
> +
> + of_node_put(remote);
> +
>   platform_set_drvdata(pdev, mic);
>   
>   mic->bridge.funcs = &mic_bridge_funcs;

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH v6 4/6] drm: exynos: dsi: Use drm panel_bridge API

2022-03-25 Thread Marek Szyprowski


On 03.03.2022 17:36, Jagan Teki wrote:
> Replace the manual panel handling code by a drm panel_bridge via
> devm_drm_of_get_bridge().
>
> Adding panel_bridge handling,
>
> - Drops drm_connector and related operations as drm_bridge_attach
>creates connector during attachment.
>
> - Drops panel pointer and iterate the bridge, so-that it can operate
>the normal bridge and panel_bridge in constitutive callbacks.
>
> This simplifies the driver and allows all components in the display
> pipeline to be treated as bridges.
>
> Signed-off-by: Jagan Teki 

Acked-by: Marek Szyprowski 

Tested-by: Marek Szyprowski 

> ---
> Changes for v6, v5:
> - none
> Changes for v4:
> - drop unneeded headers
> Changes for v3:
> - fix port number
> - add print for attached device
> Changes for v2:
> - new patch
>
>   drivers/gpu/drm/exynos/exynos_drm_dsi.c | 157 
>   1 file changed, 23 insertions(+), 134 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
> b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index 741c046513e8..953094133ed8 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -24,9 +24,7 @@
>   
>   #include 
>   #include 
> -#include 
>   #include 
> -#include 
>   #include 
>   #include 
>   #include 
> @@ -253,8 +251,6 @@ struct exynos_dsi_driver_data {
>   struct exynos_dsi {
>   struct drm_encoder encoder;
>   struct mipi_dsi_host dsi_host;
> - struct drm_connector connector;
> - struct drm_panel *panel;
>   struct list_head bridge_chain;
>   struct drm_bridge *out_bridge;
>   struct device *dev;
> @@ -285,7 +281,6 @@ struct exynos_dsi {
>   };
>   
>   #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
> -#define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector)
>   
>   static inline struct exynos_dsi *encoder_to_dsi(struct drm_encoder *e)
>   {
> @@ -1380,42 +1375,21 @@ static void exynos_dsi_enable(struct drm_encoder 
> *encoder)
>   
>   dsi->state |= DSIM_STATE_ENABLED;
>   
> - if (dsi->panel) {
> - ret = drm_panel_prepare(dsi->panel);
> - if (ret < 0)
> - goto err_put_sync;
> - } else {
> - list_for_each_entry_reverse(iter, &dsi->bridge_chain,
> - chain_node) {
> - if (iter->funcs->pre_enable)
> - iter->funcs->pre_enable(iter);
> - }
> + list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
> + if (iter->funcs->pre_enable)
> + iter->funcs->pre_enable(iter);
>   }
>   
>   exynos_dsi_set_display_mode(dsi);
>   exynos_dsi_set_display_enable(dsi, true);
>   
> - if (dsi->panel) {
> - ret = drm_panel_enable(dsi->panel);
> - if (ret < 0)
> - goto err_display_disable;
> - } else {
> - list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
> - if (iter->funcs->enable)
> - iter->funcs->enable(iter);
> - }
> + list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
> + if (iter->funcs->enable)
> + iter->funcs->enable(iter);
>   }
>   
>   dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
>   return;
> -
> -err_display_disable:
> - exynos_dsi_set_display_enable(dsi, false);
> - drm_panel_unprepare(dsi->panel);
> -
> -err_put_sync:
> - dsi->state &= ~DSIM_STATE_ENABLED;
> - pm_runtime_put(dsi->dev);
>   }
>   
>   static void exynos_dsi_disable(struct drm_encoder *encoder)
> @@ -1428,15 +1402,12 @@ static void exynos_dsi_disable(struct drm_encoder 
> *encoder)
>   
>   dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
>   
> - drm_panel_disable(dsi->panel);
> -
>   list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
>   if (iter->funcs->disable)
>   iter->funcs->disable(iter);
>   }
>   
>   exynos_dsi_set_display_enable(dsi, false);
> - drm_panel_unprepare(dsi->panel);
>   
>   list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
>   if (iter->funcs->post_disable)
> @@ -1456,70 +1427,6 @@ static void exynos_dsi_mode_set(struct drm_encoder 
> *encoder,
>   drm_mode_copy(&dsi->mode, adjusted_mode);
>   }
>   
> -static enum drm_connector_status
> -exynos_dsi_detect(struct drm_connector *connector, bool force)
> -{
> - return connector->status;
> -}
> -
> -static void exynos_dsi_connector_destroy(struct drm_connector *connector)
> -{
> - drm_connector_unregister(connector);
> - drm_connector_cleanup(connector);
> - connector->dev = NULL;
> -}
> -
> -static const struct drm_connector_funcs exynos_dsi_connector_funcs = {
> - .detect = exynos_dsi_detect,
> - .fill_modes = drm_helper_probe_single_connector_modes,
> - .destro

Re: [PATCH v6 5/6] drm: exynos: dsi: Convert to bridge driver

2022-03-25 Thread Marek Szyprowski


On 03.03.2022 17:36, Jagan Teki wrote:
> Convert the encoders to bridge drivers in order to standardize on
> a single API with built-in dumb encoder support for compatibility
> with existing component drivers.
>
> Driver bridge conversion will help to reuse the same bridge on
> different platforms as exynos dsi driver can be used as a Samsung
> DSIM and use it for i.MX8MM platform.
>
> Bridge conversion,
>
> - Drops drm_encoder_helper_funcs.
>
> - Adds drm_bridge_funcs and register a drm bridge.
>
> - Drops bridge_chain.
>
> - Separate pre_enable from enable function.
>
> - Separate post_disable from disable function.
>
> Convert it.
>
> Signed-off-by: Jagan Teki 

Acked-by: Marek Szyprowski 

Tested-by: Marek Szyprowski 

> ---
> Changes for v6, v5:
> - none
> Changes for v4:
> - add pre_enable function
> - add post_disable function
> Changes for v3:
> - move bridge add in host_attach
> - move bridge remove in host_detach
> - use flags, bridge in drm_bridge_attach in attch
> Changes for v2:
> - drop bridge_chain
>
>   drivers/gpu/drm/exynos/exynos_drm_dsi.c | 88 +
>   1 file changed, 45 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
> b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index 953094133ed8..59a4f7f52180 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -251,7 +251,7 @@ struct exynos_dsi_driver_data {
>   struct exynos_dsi {
>   struct drm_encoder encoder;
>   struct mipi_dsi_host dsi_host;
> - struct list_head bridge_chain;
> + struct drm_bridge bridge;
>   struct drm_bridge *out_bridge;
>   struct device *dev;
>   struct drm_display_mode mode;
> @@ -282,9 +282,9 @@ struct exynos_dsi {
>   
>   #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
>   
> -static inline struct exynos_dsi *encoder_to_dsi(struct drm_encoder *e)
> +static inline struct exynos_dsi *bridge_to_dsi(struct drm_bridge *b)
>   {
> - return container_of(e, struct exynos_dsi, encoder);
> + return container_of(b, struct exynos_dsi, bridge);
>   }
>   
>   enum reg_idx {
> @@ -1358,10 +1358,9 @@ static void exynos_dsi_unregister_te_irq(struct 
> exynos_dsi *dsi)
>   }
>   }
>   
> -static void exynos_dsi_enable(struct drm_encoder *encoder)
> +static void exynos_dsi_pre_enable(struct drm_bridge *bridge)
>   {
> - struct exynos_dsi *dsi = encoder_to_dsi(encoder);
> - struct drm_bridge *iter;
> + struct exynos_dsi *dsi = bridge_to_dsi(bridge);
>   int ret;
>   
>   if (dsi->state & DSIM_STATE_ENABLED)
> @@ -1374,63 +1373,64 @@ static void exynos_dsi_enable(struct drm_encoder 
> *encoder)
>   }
>   
>   dsi->state |= DSIM_STATE_ENABLED;
> +}
>   
> - list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
> - if (iter->funcs->pre_enable)
> - iter->funcs->pre_enable(iter);
> - }
> +static void exynos_dsi_enable(struct drm_bridge *bridge)
> +{
> + struct exynos_dsi *dsi = bridge_to_dsi(bridge);
>   
>   exynos_dsi_set_display_mode(dsi);
>   exynos_dsi_set_display_enable(dsi, true);
>   
> - list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
> - if (iter->funcs->enable)
> - iter->funcs->enable(iter);
> - }
> -
>   dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
> +
>   return;
>   }
>   
> -static void exynos_dsi_disable(struct drm_encoder *encoder)
> +static void exynos_dsi_disable(struct drm_bridge *bridge)
>   {
> - struct exynos_dsi *dsi = encoder_to_dsi(encoder);
> - struct drm_bridge *iter;
> + struct exynos_dsi *dsi = bridge_to_dsi(bridge);
>   
>   if (!(dsi->state & DSIM_STATE_ENABLED))
>   return;
>   
>   dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
> +}
>   
> - list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
> - if (iter->funcs->disable)
> - iter->funcs->disable(iter);
> - }
> +static void exynos_dsi_post_disable(struct drm_bridge *bridge)
> +{
> + struct exynos_dsi *dsi = bridge_to_dsi(bridge);
>   
>   exynos_dsi_set_display_enable(dsi, false);
>   
> - list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
> - if (iter->funcs->post_disable)
> - iter->funcs->post_disable(iter);
> - }
> -
>   dsi->state &= ~DSIM_STATE_ENABLED;
>   pm_runtime_put_sync(dsi->dev);
>   }
>   
> -static void exynos_dsi_mode_set(struct drm_encoder *encoder,
> - struct drm_display_mode *mode,
> - struct drm_display_mode *adjusted_mode)
> +static void exynos_dsi_mode_set(struct drm_bridge *bridge,
> + const struct drm_display_mode *mode,
> + const struct drm_display_mode *adjusted_mode)
>   {
> - struct exynos_dsi *dsi = encoder_to_dsi(encoder);
> + struct 

Re: [PATCH v6 6/6] drm: exynos: dsi: Switch to atomic funcs

2022-03-25 Thread Marek Szyprowski


On 03.03.2022 17:36, Jagan Teki wrote:
> The new support drm bridges are moving towards atomic functions.
>
> Replace atomic version of functions to continue the transition
> to the atomic API.
>
> Signed-off-by: Jagan Teki 

Acked-by: Marek Szyprowski 

Tested-by: Marek Szyprowski 

> ---
> Changes for v6, v5, v4, v3:
> - none
>
>   drivers/gpu/drm/exynos/exynos_drm_dsi.c | 25 -
>   1 file changed, 16 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
> b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index 59a4f7f52180..06130eee8df8 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -1358,7 +1358,8 @@ static void exynos_dsi_unregister_te_irq(struct 
> exynos_dsi *dsi)
>   }
>   }
>   
> -static void exynos_dsi_pre_enable(struct drm_bridge *bridge)
> +static void exynos_dsi_atomic_pre_enable(struct drm_bridge *bridge,
> +  struct drm_bridge_state 
> *old_bridge_state)
>   {
>   struct exynos_dsi *dsi = bridge_to_dsi(bridge);
>   int ret;
> @@ -1375,7 +1376,8 @@ static void exynos_dsi_pre_enable(struct drm_bridge 
> *bridge)
>   dsi->state |= DSIM_STATE_ENABLED;
>   }
>   
> -static void exynos_dsi_enable(struct drm_bridge *bridge)
> +static void exynos_dsi_atomic_enable(struct drm_bridge *bridge,
> +  struct drm_bridge_state *old_bridge_state)
>   {
>   struct exynos_dsi *dsi = bridge_to_dsi(bridge);
>   
> @@ -1387,7 +1389,8 @@ static void exynos_dsi_enable(struct drm_bridge *bridge)
>   return;
>   }
>   
> -static void exynos_dsi_disable(struct drm_bridge *bridge)
> +static void exynos_dsi_atomic_disable(struct drm_bridge *bridge,
> +   struct drm_bridge_state *old_bridge_state)
>   {
>   struct exynos_dsi *dsi = bridge_to_dsi(bridge);
>   
> @@ -1397,7 +1400,8 @@ static void exynos_dsi_disable(struct drm_bridge 
> *bridge)
>   dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
>   }
>   
> -static void exynos_dsi_post_disable(struct drm_bridge *bridge)
> +static void exynos_dsi_atomic_post_disable(struct drm_bridge *bridge,
> +struct drm_bridge_state 
> *old_bridge_state)
>   {
>   struct exynos_dsi *dsi = bridge_to_dsi(bridge);
>   
> @@ -1425,10 +1429,13 @@ static int exynos_dsi_attach(struct drm_bridge 
> *bridge,
>   }
>   
>   static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = {
> - .pre_enable = exynos_dsi_pre_enable,
> - .enable = exynos_dsi_enable,
> - .disable= exynos_dsi_disable,
> - .post_disable   = exynos_dsi_post_disable,
> + .atomic_duplicate_state = 
> drm_atomic_helper_bridge_duplicate_state,
> + .atomic_destroy_state   = 
> drm_atomic_helper_bridge_destroy_state,
> + .atomic_reset   = drm_atomic_helper_bridge_reset,
> + .atomic_pre_enable  = exynos_dsi_atomic_pre_enable,
> + .atomic_enable  = exynos_dsi_atomic_enable,
> + .atomic_disable = exynos_dsi_atomic_disable,
> + .atomic_post_disable= exynos_dsi_atomic_post_disable,
>   .mode_set   = exynos_dsi_mode_set,
>   .attach = exynos_dsi_attach,
>   };
> @@ -1597,7 +1604,7 @@ static void exynos_dsi_unbind(struct device *dev, 
> struct device *master,
>   {
>   struct exynos_dsi *dsi = dev_get_drvdata(dev);
>   
> - exynos_dsi_disable(&dsi->bridge);
> + exynos_dsi_atomic_disable(&dsi->bridge, NULL);
>   
>   mipi_dsi_host_unregister(&dsi->dsi_host);
>   }

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



Re: [PATCH] drm/vmwgfx: Propagate error on failed ioctl

2022-03-25 Thread Javier Martinez Canillas
Hello Philipp,

On 3/13/22 06:06, Philipp Sieweck wrote:
> The cases of vmw_user_bo_synccpu_grab failing with -ERESTARTSYS or -EBUSY
> are handled in vmw_user_bo_synccpu_ioctl by not printing an error message.
> However, the error value gets discarded, indicating success. This leads
> to rendering glitches and a reported drm error on the next ioctl call to
> release the handle.
> 
> This patch propagates the error value from vmw_user_synccpu_grab.
> 
> Signed-off-by: Philipp Sieweck 
> ---
>  drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 2 ++
>  1 file changed, 2 insertions(+)
>

Patch looks good to me.
 
Reviewed-by: Javier Martinez Canillas 

-- 
Best regards,

Javier Martinez Canillas
Linux Engineering
Red Hat



Re: [PATCH 1/2] dma-buf: add dma_fence_unwrap

2022-03-25 Thread Ville Syrjälä
On Fri, Mar 11, 2022 at 12:02:43PM +0100, Christian König wrote:
> Add a general purpose helper to deep dive into dma_fence_chain/dma_fence_array
> structures and iterate over all the fences in them.
> 
> This is useful when we need to flatten out all fences in those structures.
> 
> Signed-off-by: Christian König 

One of the dma-buf patches took down Intel CI. Looks like every
machine oopses in some sync_file thing now:
<1>[  260.470008] BUG: kernel NULL pointer dereference, address: 
0010
<1>[  260.470020] #PF: supervisor read access in kernel mode
<1>[  260.470025] #PF: error_code(0x) - not-present page
<6>[  260.470030] PGD 0 P4D 0 
<4>[  260.470035] Oops:  [#1] PREEMPT SMP NOPTI
<4>[  260.470040] CPU: 0 PID: 5306 Comm: core_hotunplug Not tainted 
5.17.0-CI-CI_DRM_11405+ #1
<4>[  260.470049] Hardware name: Intel Corporation Jasper Lake Client 
Platform/Jasperlake DDR4 SODIMM RVP, BIOS JSLSFWI1.R00.2385.D02.2010160831 
10/16/2020
<4>[  260.470058] RIP: 0010:dma_fence_array_first+0x19/0x20
<4>[  260.470068] Code: c3 31 c0 c3 0f 1f 00 66 2e 0f 1f 84 00 00 00 00 00 48 
85 ff 74 18 48 89 f8 48 81 7f 08 60 7f 0a 82 75 0d 48 8b 87 88 00 00 00 <48> 8b 
00 c3 31 c0 c3 31 c0 48 85 ff 74 20 48 81 7f 08 60 7f 0a 82
<4>[  260.470080] RSP: 0018:c99a7e40 EFLAGS: 00010246
<4>[  260.470086] RAX: 0010 RBX: 000b RCX: 

<4>[  260.470100] RDX: 0001 RSI: 0001 RDI: 
888109a796b8
<4>[  260.470106] RBP: 888109a796b8 R08: 0002 R09: 

<4>[  260.470112] R10: 0001 R11:  R12: 
888109a796b8
<4>[  260.470118] R13: 7ffc5d21f750 R14: 8881065be340 R15: 

<4>[  260.470124] FS:  7f08bd6d04c0() GS:5fc0() 
knlGS:
<4>[  260.470131] CS:  0010 DS:  ES:  CR0: 80050033
<4>[  260.470137] CR2: 0010 CR3: 00010e69 CR4: 
00350ef0
<4>[  260.470143] Call Trace:
<4>[  260.470146]  
<4>[  260.470149]  sync_file_ioctl+0x2eb/0xc90
<4>[  260.470157]  __x64_sys_ioctl+0x6a/0xa0
<4>[  260.470164]  do_syscall_64+0x37/0xb0
<4>[  260.470170]  entry_SYSCALL_64_after_hwframe+0x44/0xae
<4>[  260.470176] RIP: 0033:0x7f08c047750b
<4>[  260.470182] Code: 0f 1e fa 48 8b 05 85 39 0d 00 64 c7 00 26 00 00 00 48 
c7 c0 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 
01 f0 ff ff 73 01 c3 48 8b 0d 55 39 0d 00 f7 d8 64 89 01 48
<4>[  260.470195] RSP: 002b:7ffc5d21f748 EFLAGS: 0246 ORIG_RAX: 
0010
<4>[  260.470202] RAX: ffda RBX: 000a RCX: 
7f08c047750b
<4>[  260.470208] RDX: 7ffc5d21f750 RSI: c0303e03 RDI: 
000a
<4>[  260.470214] RBP: 0005 R08:  R09: 
7ffc5d21ebb0
<4>[  260.470219] R10: 7f08c0a6170e R11: 0246 R12: 

<4>[  260.470225] R13: 7ffc5d21f840 R14: 55e80d13d1b0 R15: 
0009
<4>[  260.470233]  
<4>[  260.470239] Modules linked in: vgem drm_shmem_helper fuse 
snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic ledtrig_audio 
i915 snd_hda_intel snd_intel_dspcfg snd_hda_codec x86_pkg_temp_thermal coretemp 
crct10dif_pclmul crc32_pclmul snd_hwdep ghash_clmulni_intel snd_hda_core ttm 
drm_buddy drm_dp_helper snd_pcm drm_kms_helper i2c_i801 r8169 i2c_smbus 
syscopyarea realtek sysfillrect sysimgblt fb_sys_fops prime_numbers 
intel_lpss_pci
<4>[  260.470289] CR2: 0010
<4>[  260.470312] ---[ end trace  ]---

Can we please start running dma-buf stuff through CI so this
kind of stuff doesn't keep happening so often?

-- 
Ville Syrjälä
Intel


Re: [PATCH 1/2] dma-buf: add dma_fence_unwrap

2022-03-25 Thread Christian König

Am 25.03.22 um 16:25 schrieb Ville Syrjälä:

On Fri, Mar 11, 2022 at 12:02:43PM +0100, Christian König wrote:

Add a general purpose helper to deep dive into dma_fence_chain/dma_fence_array
structures and iterate over all the fences in them.

This is useful when we need to flatten out all fences in those structures.

Signed-off-by: Christian König 

One of the dma-buf patches took down Intel CI. Looks like every
machine oopses in some sync_file thing now:
<1>[  260.470008] BUG: kernel NULL pointer dereference, address: 
0010
<1>[  260.470020] #PF: supervisor read access in kernel mode
<1>[  260.470025] #PF: error_code(0x) - not-present page
<6>[  260.470030] PGD 0 P4D 0
<4>[  260.470035] Oops:  [#1] PREEMPT SMP NOPTI
<4>[  260.470040] CPU: 0 PID: 5306 Comm: core_hotunplug Not tainted 
5.17.0-CI-CI_DRM_11405+ #1
<4>[  260.470049] Hardware name: Intel Corporation Jasper Lake Client 
Platform/Jasperlake DDR4 SODIMM RVP, BIOS JSLSFWI1.R00.2385.D02.2010160831 10/16/2020
<4>[  260.470058] RIP: 0010:dma_fence_array_first+0x19/0x20
<4>[  260.470068] Code: c3 31 c0 c3 0f 1f 00 66 2e 0f 1f 84 00 00 00 00 00 48 85 ff 
74 18 48 89 f8 48 81 7f 08 60 7f 0a 82 75 0d 48 8b 87 88 00 00 00 <48> 8b 00 c3 31 c0 
c3 31 c0 48 85 ff 74 20 48 81 7f 08 60 7f 0a 82
<4>[  260.470080] RSP: 0018:c99a7e40 EFLAGS: 00010246
<4>[  260.470086] RAX: 0010 RBX: 000b RCX: 

<4>[  260.470100] RDX: 0001 RSI: 0001 RDI: 
888109a796b8
<4>[  260.470106] RBP: 888109a796b8 R08: 0002 R09: 

<4>[  260.470112] R10: 0001 R11:  R12: 
888109a796b8
<4>[  260.470118] R13: 7ffc5d21f750 R14: 8881065be340 R15: 

<4>[  260.470124] FS:  7f08bd6d04c0() GS:5fc0() 
knlGS:
<4>[  260.470131] CS:  0010 DS:  ES:  CR0: 80050033
<4>[  260.470137] CR2: 0010 CR3: 00010e69 CR4: 
00350ef0
<4>[  260.470143] Call Trace:
<4>[  260.470146]  
<4>[  260.470149]  sync_file_ioctl+0x2eb/0xc90
<4>[  260.470157]  __x64_sys_ioctl+0x6a/0xa0
<4>[  260.470164]  do_syscall_64+0x37/0xb0
<4>[  260.470170]  entry_SYSCALL_64_after_hwframe+0x44/0xae
<4>[  260.470176] RIP: 0033:0x7f08c047750b
<4>[  260.470182] Code: 0f 1e fa 48 8b 05 85 39 0d 00 64 c7 00 26 00 00 00 48 c7 c0 
ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 
73 01 c3 48 8b 0d 55 39 0d 00 f7 d8 64 89 01 48
<4>[  260.470195] RSP: 002b:7ffc5d21f748 EFLAGS: 0246 ORIG_RAX: 
0010
<4>[  260.470202] RAX: ffda RBX: 000a RCX: 
7f08c047750b
<4>[  260.470208] RDX: 7ffc5d21f750 RSI: c0303e03 RDI: 
000a
<4>[  260.470214] RBP: 0005 R08:  R09: 
7ffc5d21ebb0
<4>[  260.470219] R10: 7f08c0a6170e R11: 0246 R12: 

<4>[  260.470225] R13: 7ffc5d21f840 R14: 55e80d13d1b0 R15: 
0009
<4>[  260.470233]  
<4>[  260.470239] Modules linked in: vgem drm_shmem_helper fuse 
snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic ledtrig_audio i915 
snd_hda_intel snd_intel_dspcfg snd_hda_codec x86_pkg_temp_thermal coretemp 
crct10dif_pclmul crc32_pclmul snd_hwdep ghash_clmulni_intel snd_hda_core ttm 
drm_buddy drm_dp_helper snd_pcm drm_kms_helper i2c_i801 r8169 i2c_smbus syscopyarea 
realtek sysfillrect sysimgblt fb_sys_fops prime_numbers intel_lpss_pci
<4>[  260.470289] CR2: 0010
<4>[  260.470312] ---[ end trace  ]---

Can we please start running dma-buf stuff through CI so this
kind of stuff doesn't keep happening so often?


I've did ran it through CI, but since the most recent patches didn't 
applied on top of drm-tip for some reason the result was just garbage.


Going to take a look into this immediately, looks like something which 
I've seen during development maybe the wrong patch was pushed to 
drm-misc-next-fixes or something like this.


Thanks for letting me know,
Christian.


Re: [PATCH] drm/amd: Re-classify some log messages in commit path

2022-03-25 Thread Alex Deucher
Thanks.  Fixed up the title when I applied it.

Alex

On Fri, Mar 25, 2022 at 10:55 AM Harry Wentland  wrote:
>
> On 2022-03-24 20:06, Sean Paul wrote:
> > From: Sean Paul 
> >
> > ATOMIC and DRIVER log categories do not typically contain per-frame log
> > messages. This patch re-classifies some messages in amd to chattier
> > categories to keep ATOMIC/DRIVER quiet.
> >
> > Signed-off-by: Sean Paul 
>
> With the subject line fixed as per Christian's comment this is
> Reviewed-by: Harry Wentland 
>
> Harry
>
> > ---
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_display.c   | 5 +++--
> >  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 
> >  2 files changed, 7 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c 
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
> > index fae5c1debfad..1fcbab2fd3c3 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
> > @@ -113,8 +113,9 @@ static void amdgpu_display_flip_work_func(struct 
> > work_struct *__work)
> >   spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
> >
> >
> > - DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_SUBMITTED, 
> > work: %p,\n",
> > -  amdgpu_crtc->crtc_id, amdgpu_crtc, 
> > work);
> > + drm_dbg_vbl(adev_to_drm(adev),
> > + "crtc:%d[%p], pflip_stat:AMDGPU_FLIP_SUBMITTED, work: 
> > %p,\n",
> > + amdgpu_crtc->crtc_id, amdgpu_crtc, work);
> >
> >  }
> >
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > index b30656959fd8..45d130f86114 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > @@ -9248,7 +9248,7 @@ static void amdgpu_dm_commit_planes(struct 
> > drm_atomic_state *state,
> >   &bundle->flip_addrs[planes_count].address,
> >   afb->tmz_surface, false);
> >
> > - DRM_DEBUG_ATOMIC("plane: id=%d dcc_en=%d\n",
> > + drm_dbg_state(state->dev, "plane: id=%d dcc_en=%d\n",
> >new_plane_state->plane->index,
> >
> > bundle->plane_infos[planes_count].dcc.enable);
> >
> > @@ -9282,7 +9282,7 @@ static void amdgpu_dm_commit_planes(struct 
> > drm_atomic_state *state,
> >   dc_plane,
> >   
> > bundle->flip_addrs[planes_count].flip_timestamp_in_us);
> >
> > - DRM_DEBUG_ATOMIC("%s Flipping to hi: 0x%x, low: 0x%x\n",
> > + drm_dbg_state(state->dev, "%s Flipping to hi: 0x%x, low: 
> > 0x%x\n",
> >__func__,
> >
> > bundle->flip_addrs[planes_count].address.grph.addr.high_part,
> >
> > bundle->flip_addrs[planes_count].address.grph.addr.low_part);
> > @@ -9624,7 +9624,7 @@ static void amdgpu_dm_atomic_commit_tail(struct 
> > drm_atomic_state *state)
> >   dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
> >   dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
> >
> > - DRM_DEBUG_ATOMIC(
> > + drm_dbg_state(state->dev,
> >   "amdgpu_crtc id:%d crtc_state_flags: enable:%d, 
> > active:%d, "
> >   "planes_changed:%d, 
> > mode_changed:%d,active_changed:%d,"
> >   "connectors_changed:%d\n",
> > @@ -10328,7 +10328,7 @@ static int dm_update_crtc_state(struct 
> > amdgpu_display_manager *dm,
> >   if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
> >   goto skip_modeset;
> >
> > - DRM_DEBUG_ATOMIC(
> > + drm_dbg_state(state->dev,
> >   "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
> >   "planes_changed:%d, mode_changed:%d,active_changed:%d,"
> >   "connectors_changed:%d\n",
>


[PATCH] dma-buf: WIP dma_fence_array_first fix

2022-03-25 Thread Christian König
Looks like somebody is creating an empty dma_fence_array.

Signed-off-by: Christian König 
---
 drivers/dma-buf/dma-fence-array.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/dma-buf/dma-fence-array.c 
b/drivers/dma-buf/dma-fence-array.c
index 52b85d292383..5c8a7084577b 100644
--- a/drivers/dma-buf/dma-fence-array.c
+++ b/drivers/dma-buf/dma-fence-array.c
@@ -159,6 +159,8 @@ struct dma_fence_array *dma_fence_array_create(int 
num_fences,
struct dma_fence_array *array;
size_t size = sizeof(*array);
 
+   WARN_ON(!num_fences || !fences);
+
/* Allocate the callback structures behind the array. */
size += num_fences * sizeof(struct dma_fence_array_cb);
array = kzalloc(size, GFP_KERNEL);
@@ -231,6 +233,9 @@ struct dma_fence *dma_fence_array_first(struct dma_fence 
*head)
if (!array)
return head;
 
+   if (!array->num_fences)
+   return NULL;
+
return array->fences[0];
 }
 EXPORT_SYMBOL(dma_fence_array_first);
-- 
2.25.1



Re: [PATCH v4 6/6] drm/msm: make mdp5/dpu devices master components

2022-03-25 Thread Stephen Boyd
Quoting Dmitry Baryshkov (2022-03-25 05:17:36)
> The msm_mdss serves several roles at this moment. It provides IRQ domain
> used by MDP5 and DPU drivers but it also serves as a component master
> for both those usecases. MDP4 (which does not have separate MDSS device)
> is the component master on it's own.
> Remove this assymmetry and make both MDP5 and DPU component masters too.
> This removes a need to care about drm/components from msm_mdss driver,
> removes an mdss pointer from struct msm_drm_private and simplifies the
> interface between mdp5/dpu and msm_drv.
>
> Signed-off-by: Dmitry Baryshkov 
> ---

Reviewed-by: Stephen Boyd 


RE: [PATCH v5 6/9] drm/msm/dp: wait for hpd high before any sink interaction

2022-03-25 Thread Sankeerth Billakanti (QUIC)


> -Original Message-
> From: Doug Anderson 
> Sent: Saturday, March 19, 2022 5:26 AM
> To: Stephen Boyd 
> Cc: Sankeerth Billakanti (QUIC) ; open list:OPEN
> FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
> ; dri-devel ;
> freedreno ; linux-arm-msm  m...@vger.kernel.org>; LKML ; Rob Clark
> ; Sean Paul ;
> quic_kalyant ; Abhinav Kumar (QUIC)
> ; Kuogee Hsieh (QUIC)
> ; Andy Gross ;
> bjorn.anders...@linaro.org; Rob Herring ;
> krzk...@kernel.org; Sean Paul ; David Airlie
> ; Daniel Vetter ; Thierry Reding
> ; Sam Ravnborg ;
> dmitry.barysh...@linaro.org; quic_vproddut 
> Subject: Re: [PATCH v5 6/9] drm/msm/dp: wait for hpd high before any sink
> interaction
> 
> Hi,
> 
> On Fri, Mar 18, 2022 at 4:27 PM Stephen Boyd 
> wrote:
> >
> > > > Pushing hpd state checking into aux transactions looks like the
> > > > wrong direction. Also, as I said up above I am concerned that even
> > > > checking the GPIO won't work and we need some way to ask the
> > > > bridge if HPD is asserted or not and then fallback to the GPIO
> > > > method if the display phy/controller doesn't have support to check
> > > > HPD internally. Something on top of DRM_BRIDGE_OP_HPD?
> > >
> > > If we could somehow get the HPD status from the bridge in the panel
> > > driver it definitely would be convenient. It does feel like that's
> > > an improvement that could be done later, though. We've already
> > > landed a few instances of doing what's done here, like for
> > > parade-ps8640 and analogix_dp. I suspect designing a new mechanism
> > > might not be the most trivial.
> >
> > What is done in the bridge drivers is to wait for a fixed timeout and
> > assume aux is ready? Or is it something else? If there's just a fixed
> > timeout for the eDP case it sounds OK to do that for now and we can
> > fine tune it later to actually check HPD status register before the
> > panel tries to read EDID.
> 
> Right. For the parade chip (which is only used for eDP as far as I know--never
> DP) waits for up to 200 ms. See ps8640_ensure_hpd().
> 
> So I guess tl;dr to Sankeerth that it's OK for his patch to have the wait in 
> the
> aux transfer function, but only for eDP. Other discussions here are about
> how we could make it better in future patches.
> 
> 

The aux transactions for external DP are initiated by the dp_display driver 
only after the
display is hot plugged to the connector. The phy_init is necessary for the aux 
transactions
to take place. So, for the DP case, like Doug mentioned below, this patch is 
introducing
an overhead of three register reads to detect hpd_high before performing aux 
transactions.
So, we felt this was okay to do for DP.

On the other hand, for eDP, it is necessary to wait for panel ready through 
this hpd connect status.
Currently there is no way to know which type of connector it is in the dp_aux 
sub-module.

However, as the discussion suggested, to have the wait only for eDP, I am 
thinking to pass the
connector_type information to aux sub-module and register different 
aux_transfer functions
for eDP and DP. The eDP transfer function will wait for hpd_high and the DP 
transfer function
will be same as the one before this patch.

What do you think?

> > > I haven't actually tried it, but I suspect that to get something
> > > like what you're talking about we'd have to get the rest of drm to
> > > know that for eDP ports that it should assume something is connected
> > > _regardless_ of what the "detect" / "HPD" options say. Then we'd
> > > have to extend the edp-panel code to be able to be able to query the
> > > next bridge in the chain if a GPIO wasn't provided.
> >
> > Can the panel interrogate the bridge chain somehow? It feels like
> > either something in the chain should know the status of HPD (the case
> > here where display controller in the SoC knows) or it should be a gpio
> > to the panel (trogdor case). The bridge ops can implement
> > DRM_BRIDGE_OP_HPD and the first bridge from the encoder that supports
> > HPD can implement some sort of "wait for hpd asserted" function that
> > the panel then uses once it powers up the panel during probe. If the
> > panel has a gpio and nothing else in the chain can detect hpd then the
> > panel polls the gpio, or it waits for the amount of time delay after
> > powering on the panel if the panel's hpd function is called.
> 
> Yeah, there ought to be some way to make something like that work. I don't
> think it's just DRM_BRIDGE_OP_HPD, though, for a few reasons:
> 
> 1. That operation actually specifically means that HPD can cause an interrupt
> and that the bridge promises to call drm_bridge_hpd_notify() when the
> interrupt occurs. It seems to work hand-in-hand with
> "DRM_BRIDGE_OP_DETECT". I know it's legit to advertise "detect"
> without "HPD" (you have an HPD line that can be polled but not cause
> interrupts) but I'd have to research whether it's legal to advertise "HPD"
> without "detect".
> 
> 2. If it were up to me, I'd rather avoid conflating what we ne

Re: Commit messages

2022-03-25 Thread Paul Menzel

Dear Christian, dear Daniel, dear Alex,


Am 23.03.22 um 16:32 schrieb Christian König:

Am 23.03.22 um 16:24 schrieb Daniel Stone:

On Wed, 23 Mar 2022 at 15:14, Alex Deucher  wrote:
On Wed, Mar 23, 2022 at 11:04 AM Daniel Stone  
wrote:

That's not what anyone's saying here ...

No-one's demanding AMD publish RTL, or internal design docs, or
hardware specs, or URLs to JIRA tickets no-one can access.

This is a large and invasive commit with pretty big ramifications;
containing exactly two lines of commit message, one of which just
duplicates the subject.

It cannot be the case that it's completely impossible to provide any
justification, background, or details, about this commit being made.
Unless, of course, it's to fix a non-public security issue, that is
reasonable justification for eliding some of the details. But then
again, 'huge change which is very deliberately opaque' is a really
good way to draw a lot of attention to the commit, and it would be
better to provide more detail about the change to help it slip under
the radar.

If dri-devel@ isn't allowed to inquire about patches which are posted,
then CCing the list is just a façade; might as well just do it all
internally and periodically dump out pull requests.

I think we are in agreement. I think the withheld information
Christian was referring to was on another thread with Christian and
Paul discussing a workaround for a hardware bug:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.spinics.net%2Flists%2Famd-gfx%2Fmsg75908.html&data=04%7C01%7Cchristian.koenig%40amd.com%7C6a3f2815d83b4872577008da0ce1347a%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637836458652370599%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sdata=QtNB0XHMhTgH%2FNHMwF23Qn%2BgSdYyHJSenbpP%2FHG%2BkxE%3D&reserved=0 


(Thank you Microsoft for keeping us safe.)

I guess it proves, how assuming what other people should know/have read, 
especially when crossing message threads, is causing confusion and 
misunderstandings.



Right, that definitely seems like some crossed wires. I don't see
anything wrong with that commit at all: the commit message and a
comment notes that there is a hardware issue preventing Raven from
being able to do TMZ+GTT, and the code does the very straightforward
and obvious thing to ensure that on VCN 1.0, any TMZ buffer must be
VRAM-placed.


My questions were:

Where is that documented, and how can this be reproduced? 


Shouldn’t these be answered by the commit message? In five(?) years, 
somebody, maybe even with access to the currently non-public documents, 
finds a fault in the commit, and would be helped by having an 
document/errata number where to look at. To verify the fix, the 
developer would need a method to produce the error, so why not just 
share it?


Also, I assume that workarounds often come with downsides, as otherwise 
it would have been programmed like this from the beginning, or instead 
of “workaround” it would be called “improvement”. Shouldn’t that also be 
answered?


So totally made-up example:

Currently, there is a graphics corruption running X on system Y. This is 
caused by a hardware bug in Raven ASIC (details internal document 
#/AMD-Jira #N), and can be worked around by [what is in the commit 
message].


The workaround does not affect the performance, and testing X shows the 
error is fixed.



This one, on the other hand, is much less clear ...


Yes, completely agree. I mean a good bunch of comments on commit 
messages are certainly valid and we could improve them.


That’d be great.

But this patch here was worked on by both AMD and Intel developers. 
Where both sides and I think even people from other companies perfectly 
understands why, what, how etc...


When now somebody comes along and asks for a whole explanation of the 
context why we do it then that sounds really strange to me.


The motivation should be part of the commit message. I didn’t mean 
anyone to rewrite buddy memory allocator Wikipedia article [1]. But the 
commit message at hand for switching the allocator is definitely too terse.



Kind regards,

Paul


[1]: https://en.wikipedia.org/wiki/Buddy_memory_allocation


  1   2   >