Re: [PATCH v1 3/5] treewide: use get_random_u32() when possible

2022-10-12 Thread Joe Perches
On Wed, 2022-10-12 at 21:29 +, David Laight wrote:
> From: Joe Perches
> > Sent: 12 October 2022 20:17
> > 
> > On Wed, 2022-10-05 at 23:48 +0200, Jason A. Donenfeld wrote:
> > > The prandom_u32() function has been a deprecated inline wrapper around
> > > get_random_u32() for several releases now, and compiles down to the
> > > exact same code. Replace the deprecated wrapper with a direct call to
> > > the real function.
> > []
> > > diff --git a/drivers/infiniband/hw/cxgb4/cm.c 
> > > b/drivers/infiniband/hw/cxgb4/cm.c
> > []
> > > @@ -734,7 +734,7 @@ static int send_connect(struct c4iw_ep *ep)
> > >  >com.remote_addr;
> > >   int ret;
> > >   enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type;
> > > - u32 isn = (prandom_u32() & ~7UL) - 1;
> > > + u32 isn = (get_random_u32() & ~7UL) - 1;
> > 
> > trivia:
> > 
> > There are somewhat odd size mismatches here.
> > 
> > I had to think a tiny bit if random() returned a value from 0 to 7
> > and was promoted to a 64 bit value then truncated to 32 bit.
> > 
> > Perhaps these would be clearer as ~7U and not ~7UL
> 
> That makes no difference - the compiler will generate the same code.

True, more or less.  It's more a question for the reader.

> The real question is WTF is the code doing?

True.

> The '& ~7u' clears the bottom 3 bits.
> The '- 1' then sets the bottom 3 bits and decrements the
> (random) high bits.

Right.

> So is the same as get_random_u32() | 7.

True, it's effectively the same as the upper 29 bits are random
anyway and the bottom 3 bits are always set.

> But I bet the coder had something else in mind.

Likely.

And it was also likely copy/pasted a few times.


[PATCH v2 3/7] drm/i915/uc: use different ggtt pin offsets for uc loads

2022-10-12 Thread Daniele Ceraolo Spurio
Our current FW loading process is the same for all FWs:

- Pin FW to GGTT at the start of the ggtt->uc_fw node
- Load the FW
- Unpin

This worked because we didn't have a case where 2 FWs would be loaded on
the same GGTT at the same time. On MTL, however, this can happend if both
GTs are reset at the same time, so we can't pin everything in the same
spot and we need to use separate offset. For simplicity, instead of
calculating the exact required size, we reserve a 2MB slot for each fw.

v2: fail fetch if FW is > 2MBs, improve comments (John)

Signed-off-by: Daniele Ceraolo Spurio 
Cc: John Harrison 
Cc: Alan Previn 
---
 drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 30 +---
 drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h | 13 ++
 2 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c 
b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
index de2843dc1307..021290a26195 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
@@ -575,6 +575,17 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
err = firmware_request_nowarn(, uc_fw->file_selected.path, dev);
memcpy(_ideal, _fw->file_wanted, sizeof(file_ideal));
 
+   if (!err && fw->size > INTEL_UC_RSVD_GGTT_PER_FW) {
+   drm_err(>drm,
+   "%s firmware %s: size (%zuKB) exceeds max supported 
size (%uKB)\n",
+   intel_uc_fw_type_repr(uc_fw->type), 
uc_fw->file_selected.path,
+   fw->size / SZ_1K, INTEL_UC_RSVD_GGTT_PER_FW / SZ_1K);
+
+   /* try to find another blob to load */
+   release_firmware(fw);
+   err = -ENOENT;
+   }
+
/* Any error is terminal if overriding. Don't bother searching for 
older versions */
if (err && intel_uc_fw_is_overridden(uc_fw))
goto fail;
@@ -677,14 +688,28 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
 
 static u32 uc_fw_ggtt_offset(struct intel_uc_fw *uc_fw)
 {
-   struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt;
+   struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
+   struct i915_ggtt *ggtt = gt->ggtt;
struct drm_mm_node *node = >uc_fw;
+   u32 offset = uc_fw->type * INTEL_UC_RSVD_GGTT_PER_FW;
+
+   /*
+* To keep the math simple, we use 8MB for the root tile and 8MB for
+* the media one. This will need to be updated if we ever have more
+* than 1 media GT
+*/
+   BUILD_BUG_ON(INTEL_UC_FW_NUM_TYPES * INTEL_UC_RSVD_GGTT_PER_FW > SZ_8M);
+   GEM_BUG_ON(gt->type == GT_MEDIA && gt->info.id > 1);
+   if (gt->type == GT_MEDIA)
+   offset += SZ_8M;
 
GEM_BUG_ON(!drm_mm_node_allocated(node));
GEM_BUG_ON(upper_32_bits(node->start));
GEM_BUG_ON(upper_32_bits(node->start + node->size - 1));
+   GEM_BUG_ON(offset + uc_fw->obj->base.size > node->size);
+   GEM_BUG_ON(uc_fw->obj->base.size > INTEL_UC_RSVD_GGTT_PER_FW);
 
-   return lower_32_bits(node->start);
+   return lower_32_bits(node->start + offset);
 }
 
 static void uc_fw_bind_ggtt(struct intel_uc_fw *uc_fw)
@@ -699,7 +724,6 @@ static void uc_fw_bind_ggtt(struct intel_uc_fw *uc_fw)
dummy->bi.pages = obj->mm.pages;
 
GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
-   GEM_BUG_ON(dummy->node_size > ggtt->uc_fw.size);
 
/* uc_fw->obj cache domains were not controlled across suspend */
if (i915_gem_object_has_struct_page(obj))
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h 
b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
index cb586f7df270..7b3db41efa6e 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
@@ -6,6 +6,7 @@
 #ifndef _INTEL_UC_FW_H_
 #define _INTEL_UC_FW_H_
 
+#include 
 #include 
 #include "intel_uc_fw_abi.h"
 #include "intel_device_info.h"
@@ -114,6 +115,18 @@ struct intel_uc_fw {
 
(uc)->fw.file_selected.minor_ver, \
 
(uc)->fw.file_selected.patch_ver))
 
+/*
+ * When we load the uC binaries, we pin them in a reserved section at the top 
of
+ * the GGTT, which is ~18 MBs. On multi-GT systems where the GTs share the 
GGTT,
+ * we also need to make sure that each binary is pinned to a unique location
+ * during load, because the different GT can go through the FW load at the same
+ * time. Given that the available space is much greater than what is required 
by
+ * the binaries, to keep things simple instead of dynamically partitioning the
+ * reserved section to make space for all the blobs we can just reserve a 
static
+ * chunk for each binary.
+ */
+#define INTEL_UC_RSVD_GGTT_PER_FW SZ_2M
+
 #ifdef CONFIG_DRM_I915_DEBUG_GUC
 void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
   enum intel_uc_fw_status status);
-- 
2.37.3



[PATCH v2 4/7] drm/i915/guc: Add GuC deprivilege feature to MTL

2022-10-12 Thread Daniele Ceraolo Spurio
From: Stuart Summers 

MTL supports GuC deprivilege. Add the feature flag to this platform.

Signed-off-by: Stuart Summers 
Cc: Radhakrishna Sripada 
Cc: John Harrison 
Cc: Alan Previn 
Reviewed-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_pci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 38460a0bd7cb..c252ef31a610 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -1145,6 +1145,7 @@ static const struct intel_device_info mtl_info = {
.extra_gt_list = xelpmp_extra_gt,
.has_flat_ccs = 0,
.has_gmd_id = 1,
+   .has_guc_deprivilege = 1,
.has_snoop = 1,
.__runtime.memory_regions = REGION_SMEM | REGION_STOLEN_LMEM,
.__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(CCS0),
-- 
2.37.3



[PATCH v2 1/7] drm/i915/huc: only load HuC on GTs that have VCS engines

2022-10-12 Thread Daniele Ceraolo Spurio
On MTL the primary GT doesn't have any media capabilities, so no video
engines and no HuC. We must therefore skip the HuC fetch and load on
that specific case. Given that other multi-GT platforms might have HuC
on the primary GT, we can't just check for that and it is easier to
instead check for the lack of VCS engines.

Based on code from Aravind Iddamsetty

v2: clarify which engine_mask is used for each GT and why (Tvrtko)

Signed-off-by: Daniele Ceraolo Spurio 
Cc: Aravind Iddamsetty 
Cc: John Harrison 
Cc: Alan Previn 
Cc: Tvrtko Ursulin 
Reviewed-by: Aravind Iddamsetty  #v1
---
 drivers/gpu/drm/i915/gt/uc/intel_huc.c | 29 ++
 drivers/gpu/drm/i915/i915_drv.h|  9 +---
 2 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
index 4d1cc383b681..ca170ea3426c 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
@@ -203,12 +203,41 @@ void intel_huc_unregister_gsc_notifier(struct intel_huc 
*huc, struct bus_type *b
huc->delayed_load.nb.notifier_call = NULL;
 }
 
+static bool vcs_supported(struct intel_gt *gt)
+{
+   intel_engine_mask_t mask = gt->info.engine_mask;
+
+   /*
+* We reach here from i915_driver_early_probe for the primary GT before
+* its engine mask is set, so we use the device info engine mask for it;
+* this means we're not taking VCS fusing into account, but if the
+* primary GT supports VCS engines we expect at least one of them to
+* remain unfused so we're fine.
+* For other GTs we expect the GT-specific mask to be set before we
+* call this function.
+*/
+   GEM_BUG_ON(!gt_is_root(gt) && !gt->info.engine_mask);
+
+   if (gt_is_root(gt))
+   mask = RUNTIME_INFO(gt->i915)->platform_engine_mask;
+   else
+   mask = gt->info.engine_mask;
+
+   return __ENGINE_INSTANCES_MASK(mask, VCS0, I915_MAX_VCS);
+}
+
 void intel_huc_init_early(struct intel_huc *huc)
 {
struct drm_i915_private *i915 = huc_to_gt(huc)->i915;
+   struct intel_gt *gt = huc_to_gt(huc);
 
intel_uc_fw_init_early(>fw, INTEL_UC_FW_TYPE_HUC);
 
+   if (!vcs_supported(gt)) {
+   intel_uc_fw_change_status(>fw, 
INTEL_UC_FIRMWARE_NOT_SUPPORTED);
+   return;
+   }
+
if (GRAPHICS_VER(i915) >= 11) {
huc->status.reg = GEN11_HUC_KERNEL_LOAD_INFO;
huc->status.mask = HUC_LOAD_SUCCESSFUL;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 90ed8e6db2fe..90a347140e90 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -776,12 +776,15 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
 #define __HAS_ENGINE(engine_mask, id) ((engine_mask) & BIT(id))
 #define HAS_ENGINE(gt, id) __HAS_ENGINE((gt)->info.engine_mask, id)
 
-#define ENGINE_INSTANCES_MASK(gt, first, count) ({ \
+#define __ENGINE_INSTANCES_MASK(mask, first, count) ({ \
unsigned int first__ = (first); \
unsigned int count__ = (count); \
-   ((gt)->info.engine_mask &   
\
-GENMASK(first__ + count__ - 1, first__)) >> first__;   \
+   ((mask) & GENMASK(first__ + count__ - 1, first__)) >> first__;  \
 })
+
+#define ENGINE_INSTANCES_MASK(gt, first, count) \
+   __ENGINE_INSTANCES_MASK((gt)->info.engine_mask, first, count)
+
 #define RCS_MASK(gt) \
ENGINE_INSTANCES_MASK(gt, RCS0, I915_MAX_RCS)
 #define BCS_MASK(gt) \
-- 
2.37.3



[PATCH v2 5/7] drm/i915/mtl: Handle wopcm per-GT and limit calculations.

2022-10-12 Thread Daniele Ceraolo Spurio
From: Aravind Iddamsetty 

With MTL standalone media architecture the wopcm layout has changed with
separate partitioning in WOPCM for GCD/GT GuC and SA Media GuC. The size
of WOPCM is 4MB with lower 2MB for SA Media and upper 2MB for GCD/GT.

+=+===> ++ <== WOPCM TOP
^ ^ ||
| | ||
|GCD|   GCD RC6 Image|
|GuC|Power Context   |
|WOPCM  ||
|Size   ++
| | |   GCD GuC Image|
| | ||
| v ||
| +===> ++ <== SA Media GuC WOPCM Top
| ^ ||
|   SA Media||
|GuC| SA Media RC6 Image |
|   WOPCM   |Power Context   |
|Size   ||
  WOPCM   | ++
| | ||
| | | SA Media GuC Image |
| v ||
| +===> ++ <== GuC WOPCM base
|   | WOPCM RSVD |
|   +--- + <== HuC Firmware Top
v   |  HuC FW|
+=> ++ <== WOPCM Base

Given that MTL has GuC deprivilege, the WOPCM registers are pre-locked
by the bios. Therefore, we can skip all the math for the partitioning
and just limit ourselves to sanity checking the values.

v2: fix makefile file ordering (Jani)

Signed-off-by: Aravind Iddamsetty 
Signed-off-by: Daniele Ceraolo Spurio 
Cc: Matt Roper 
Cc: John Harrison 
Cc: Alan Previn 
Cc: Jani Nikula 
---
 drivers/gpu/drm/i915/Makefile   |  5 ++-
 drivers/gpu/drm/i915/gt/intel_ggtt.c|  2 +-
 drivers/gpu/drm/i915/gt/intel_gt.c  |  1 +
 drivers/gpu/drm/i915/gt/intel_gt_types.h|  2 +
 drivers/gpu/drm/i915/{ => gt}/intel_wopcm.c | 48 +++--
 drivers/gpu/drm/i915/{ => gt}/intel_wopcm.h |  0
 drivers/gpu/drm/i915/gt/uc/intel_uc.c   |  4 +-
 drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c| 14 +++---
 drivers/gpu/drm/i915/i915_driver.c  |  2 -
 drivers/gpu/drm/i915/i915_drv.h |  3 --
 drivers/gpu/drm/i915/i915_gem.c |  5 ++-
 11 files changed, 55 insertions(+), 31 deletions(-)
 rename drivers/gpu/drm/i915/{ => gt}/intel_wopcm.c (86%)
 rename drivers/gpu/drm/i915/{ => gt}/intel_wopcm.h (100%)

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index f8cc1eb52626..4101b3507346 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -127,9 +127,11 @@ gt-y += \
gt/intel_sseu.o \
gt/intel_sseu_debugfs.o \
gt/intel_timeline.o \
+   gt/intel_wopcm.o \
gt/intel_workarounds.o \
gt/shmem_utils.o \
gt/sysfs_engines.o
+
 # x86 intel-gtt module support
 gt-$(CONFIG_X86) += gt/intel_ggtt_gmch.o
 # autogenerated null render state
@@ -183,8 +185,7 @@ i915-y += \
  i915_trace_points.o \
  i915_ttm_buddy_manager.o \
  i915_vma.o \
- i915_vma_resource.o \
- intel_wopcm.o
+ i915_vma_resource.o
 
 # general-purpose microcontroller (GuC) support
 i915-y += gt/uc/intel_uc.o \
diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c 
b/drivers/gpu/drm/i915/gt/intel_ggtt.c
index 5c67e49aacf6..b30560ab1c1b 100644
--- a/drivers/gpu/drm/i915/gt/intel_ggtt.c
+++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c
@@ -560,7 +560,7 @@ static int init_ggtt(struct i915_ggtt *ggtt)
 * why.
 */
ggtt->pin_bias = max_t(u32, I915_GTT_PAGE_SIZE,
-  intel_wopcm_guc_size(>vm.i915->wopcm));
+  intel_wopcm_guc_size(>vm.gt->wopcm));
 
ret = intel_vgt_balloon(ggtt);
if (ret)
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c 
b/drivers/gpu/drm/i915/gt/intel_gt.c
index b367cfff48d5..a95eb0b656d2 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -56,6 +56,7 @@ void intel_gt_common_init_early(struct intel_gt *gt)
seqcount_mutex_init(>tlb.seqno, >tlb.invalidate_lock);
intel_gt_pm_init_early(gt);
 
+   intel_wopcm_init_early(>wopcm);
intel_uc_init_early(>uc);
intel_rps_init_early(>rps);
 }
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h 
b/drivers/gpu/drm/i915/gt/intel_gt_types.h
index 30003d68fd51..a23cd3af5bf2 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h
@@ -30,6 +30,7 @@
 #include "intel_migrate_types.h"
 #include "intel_wakeref.h"
 #include "pxp/intel_pxp_types.h"
+#include "intel_wopcm.h"
 
 struct drm_i915_private;
 struct i915_ggtt;
@@ -98,6 +99,7 @@ struct intel_gt {
 
struct intel_uc uc;
struct intel_gsc gsc;
+   struct intel_wopcm wopcm;
 
struct {
/* Serialize global tlb invalidations */
diff --git 

[PATCH v2 7/7] drm/i915/guc: handle interrupts from media GuC

2022-10-12 Thread Daniele Ceraolo Spurio
The render and media GuCs share the same interrupt enable register, so
we can no longer disable interrupts when we disable communication for
one of the GuCs as this would impact the other GuC. Instead, we keep the
interrupts always enabled in HW and use a variable in the GuC structure
to determine if we want to service the received interrupts or not.

v2: use MTL_ prefix for reg definition (Matt)

Signed-off-by: Daniele Ceraolo Spurio 
Cc: Matt Roper 
Cc: John Harrison 
Cc: Alan Previn 
---
 drivers/gpu/drm/i915/gt/intel_gt_irq.c  | 21 ++
 drivers/gpu/drm/i915/gt/intel_gt_regs.h |  2 ++
 drivers/gpu/drm/i915/gt/uc/intel_guc.c  | 29 ++---
 drivers/gpu/drm/i915/gt/uc/intel_guc.h  |  5 -
 drivers/gpu/drm/i915/gt/uc/intel_uc.c   |  8 +--
 5 files changed, 45 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c 
b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
index f26882fdc24c..f6805088c0eb 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
@@ -17,6 +17,9 @@
 
 static void guc_irq_handler(struct intel_guc *guc, u16 iir)
 {
+   if (unlikely(!guc->interrupts.enabled))
+   return;
+
if (iir & GUC_INTR_GUC2HOST)
intel_guc_to_host_event_handler(guc);
 }
@@ -249,6 +252,7 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
 {
struct intel_uncore *uncore = gt->uncore;
u32 irqs = GT_RENDER_USER_INTERRUPT;
+   u32 guc_mask = intel_uc_wants_guc(>uc) ? GUC_INTR_GUC2HOST : 0;
const u32 gsc_mask = GSC_IRQ_INTF(0) | GSC_IRQ_INTF(1);
u32 dmask;
u32 smask;
@@ -299,6 +303,19 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
if (HAS_HECI_GSC(gt->i915))
intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_MASK, 
~gsc_mask);
 
+   if (guc_mask) {
+   /* the enable bit is common for both GTs but the masks are 
separate */
+   u32 mask = gt->type == GT_MEDIA ?
+   REG_FIELD_PREP(ENGINE0_MASK, guc_mask) :
+   REG_FIELD_PREP(ENGINE1_MASK, guc_mask);
+
+   intel_uncore_write(uncore, GEN11_GUC_SG_INTR_ENABLE,
+  REG_FIELD_PREP(ENGINE1_MASK, guc_mask));
+
+   /* we might not be the first GT to write this reg */
+   intel_uncore_rmw(uncore, MTL_GUC_MGUC_INTR_MASK, mask, 0);
+   }
+
/*
 * RPS interrupts will get enabled/disabled on demand when RPS itself
 * is enabled/disabled.
@@ -307,10 +324,6 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
gt->pm_imr = ~gt->pm_ier;
intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0);
intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_MASK,  ~0);
-
-   /* Same thing for GuC interrupts */
-   intel_uncore_write(uncore, GEN11_GUC_SG_INTR_ENABLE, 0);
-   intel_uncore_write(uncore, GEN11_GUC_SG_INTR_MASK,  ~0);
 }
 
 void gen5_gt_irq_handler(struct intel_gt *gt, u32 gt_iir)
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h 
b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
index 7f79bbf97828..8b597a918f24 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
@@ -1523,6 +1523,7 @@
 #define   GEN11_CSME   (31)
 #define   GEN11_GUNIT  (28)
 #define   GEN11_GUC(25)
+#define   MTL_MGUC (24)
 #define   GEN11_WDPERF (20)
 #define   GEN11_KCR(19)
 #define   GEN11_GTPM   (16)
@@ -1577,6 +1578,7 @@
 #define GEN11_VECS0_VECS1_INTR_MASK_MMIO(0x1900d0)
 #define GEN12_VECS2_VECS3_INTR_MASK_MMIO(0x1900d4)
 #define GEN11_GUC_SG_INTR_MASK _MMIO(0x1900e8)
+#define MTL_GUC_MGUC_INTR_MASK _MMIO(0x1900e8) /* MTL+ */
 #define GEN11_GPM_WGBOXPERF_INTR_MASK  _MMIO(0x1900ec)
 #define GEN11_CRYPTO_RSVD_INTR_MASK_MMIO(0x1900f0)
 #define GEN11_GUNIT_CSME_INTR_MASK _MMIO(0x1900f4)
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index b3600be61a9a..09f2a673aa19 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -98,6 +98,8 @@ static void gen9_enable_guc_interrupts(struct intel_guc *guc)
 gt->pm_guc_events);
gen6_gt_pm_enable_irq(gt, gt->pm_guc_events);
spin_unlock_irq(gt->irq_lock);
+
+   guc->interrupts.enabled = true;
 }
 
 static void gen9_disable_guc_interrupts(struct intel_guc *guc)
@@ -105,6 +107,7 @@ static void gen9_disable_guc_interrupts(struct intel_guc 
*guc)
struct intel_gt *gt = guc_to_gt(guc);
 
assert_rpm_wakelock_held(>i915->runtime_pm);
+   guc->interrupts.enabled = false;
 
spin_lock_irq(gt->irq_lock);
 
@@ -116,39 +119,39 

[PATCH v2 2/7] drm/i915/uc: fetch uc firmwares for each GT

2022-10-12 Thread Daniele Ceraolo Spurio
The FW binaries are independently loaded on each GT. On MTL, the memory
is shared so we could potentially re-use a single allocation, but on
discrete multi-gt platforms we are going to need independent copies,
so it is easier to do the same on MTL as well, given that the amount
of duplicated memory is relatively small (~500K).

Signed-off-by: Daniele Ceraolo Spurio 
Cc: John Harrison 
Cc: Alan Previn 
Reviewed-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_gem.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 55d605c0c55d..9093d2be9e1c 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1140,7 +1140,8 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
if (ret)
return ret;
 
-   intel_uc_fetch_firmwares(_gt(dev_priv)->uc);
+   for_each_gt(gt, dev_priv, i)
+   intel_uc_fetch_firmwares(>uc);
intel_wopcm_init(_priv->wopcm);
 
ret = i915_init_ggtt(dev_priv);
-- 
2.37.3



[PATCH v2 6/7] drm/i915/guc: define media GT GuC send regs

2022-10-12 Thread Daniele Ceraolo Spurio
The media GT shares the G-unit with the root GT, so a second set of
communication registers is required for the media GuC.

Signed-off-by: Daniele Ceraolo Spurio 
Cc: John Harrison 
Cc: Alan Previn 
Reviewed-by: John Harrison 
---
 drivers/gpu/drm/i915/gt/uc/intel_guc.c | 14 ++
 drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h |  2 ++
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index 27b09ba1d295..b3600be61a9a 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -156,7 +156,8 @@ static void gen11_disable_guc_interrupts(struct intel_guc 
*guc)
 
 void intel_guc_init_early(struct intel_guc *guc)
 {
-   struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
+   struct intel_gt *gt = guc_to_gt(guc);
+   struct drm_i915_private *i915 = gt->i915;
 
intel_uc_fw_init_early(>fw, INTEL_UC_FW_TYPE_GUC);
intel_guc_ct_init_early(>ct);
@@ -168,12 +169,17 @@ void intel_guc_init_early(struct intel_guc *guc)
mutex_init(>send_mutex);
spin_lock_init(>irq_lock);
if (GRAPHICS_VER(i915) >= 11) {
-   guc->notify_reg = GEN11_GUC_HOST_INTERRUPT;
guc->interrupts.reset = gen11_reset_guc_interrupts;
guc->interrupts.enable = gen11_enable_guc_interrupts;
guc->interrupts.disable = gen11_disable_guc_interrupts;
-   guc->send_regs.base =
-   i915_mmio_reg_offset(GEN11_SOFT_SCRATCH(0));
+   if (gt->type == GT_MEDIA) {
+   guc->notify_reg = MEDIA_GUC_HOST_INTERRUPT;
+   guc->send_regs.base = 
i915_mmio_reg_offset(MEDIA_SOFT_SCRATCH(0));
+   } else {
+   guc->notify_reg = GEN11_GUC_HOST_INTERRUPT;
+   guc->send_regs.base = 
i915_mmio_reg_offset(GEN11_SOFT_SCRATCH(0));
+   }
+
guc->send_regs.count = GEN11_SOFT_SCRATCH_COUNT;
 
} else {
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h
index a7092f711e9c..9915de32e894 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h
@@ -36,6 +36,7 @@
 #define SOFT_SCRATCH_COUNT 16
 
 #define GEN11_SOFT_SCRATCH(n)  _MMIO(0x190240 + (n) * 4)
+#define MEDIA_SOFT_SCRATCH(n)  _MMIO(0x190310 + (n) * 4)
 #define GEN11_SOFT_SCRATCH_COUNT   4
 
 #define UOS_RSA_SCRATCH(i) _MMIO(0xc200 + (i) * 4)
@@ -101,6 +102,7 @@
 #define GUC_SEND_INTERRUPT _MMIO(0xc4c8)
 #define   GUC_SEND_TRIGGER   (1<<0)
 #define GEN11_GUC_HOST_INTERRUPT   _MMIO(0x1901f0)
+#define MEDIA_GUC_HOST_INTERRUPT   _MMIO(0x190304)
 
 #define GEN12_GUC_SEM_INTR_ENABLES _MMIO(0xc71c)
 #define   GUC_SEM_INTR_ROUTE_TO_GUCBIT(31)
-- 
2.37.3



[PATCH v2 0/7] drm/i915: prepare for uC loading on MTL

2022-10-12 Thread Daniele Ceraolo Spurio
The introduction of the media GT brings a few changes for GuC/HuC. The
main difference between the 2 GTs is that only the media one has the
HuC, while both have the GuC. Also, the fact that both GTs use the same
G-unit and GGTT means we now have parallel interrupt/communication
paths. Lastly, WOPCM is divided between the two GTs, with each having
their own private chunk.

v2: address review comments

Cc: Matt Roper 
Cc: John Harrison 
Cc: Alan Previn 
Cc: Aravind Iddamsetty 
Cc: Radhakrishna Sripada 

Aravind Iddamsetty (1):
  drm/i915/mtl: Handle wopcm per-GT and limit calculations.

Daniele Ceraolo Spurio (5):
  drm/i915/huc: only load HuC on GTs that have VCS engines
  drm/i915/uc: fetch uc firmwares for each GT
  drm/i915/uc: use different ggtt pin offsets for uc loads
  drm/i915/guc: define media GT GuC send regs
  drm/i915/guc: handle interrupts from media GuC

Stuart Summers (1):
  drm/i915/guc: Add GuC deprivilege feature to MTL

 drivers/gpu/drm/i915/Makefile   |  5 ++-
 drivers/gpu/drm/i915/gt/intel_ggtt.c|  2 +-
 drivers/gpu/drm/i915/gt/intel_gt.c  |  1 +
 drivers/gpu/drm/i915/gt/intel_gt_irq.c  | 21 +++--
 drivers/gpu/drm/i915/gt/intel_gt_regs.h |  2 +
 drivers/gpu/drm/i915/gt/intel_gt_types.h|  2 +
 drivers/gpu/drm/i915/{ => gt}/intel_wopcm.c | 48 +++--
 drivers/gpu/drm/i915/{ => gt}/intel_wopcm.h |  0
 drivers/gpu/drm/i915/gt/uc/intel_guc.c  | 43 ++
 drivers/gpu/drm/i915/gt/uc/intel_guc.h  |  5 ++-
 drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h  |  2 +
 drivers/gpu/drm/i915/gt/uc/intel_huc.c  | 29 +
 drivers/gpu/drm/i915/gt/uc/intel_uc.c   | 12 --
 drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c| 44 +++
 drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h| 13 ++
 drivers/gpu/drm/i915/i915_driver.c  |  2 -
 drivers/gpu/drm/i915/i915_drv.h | 12 +++---
 drivers/gpu/drm/i915/i915_gem.c |  6 ++-
 drivers/gpu/drm/i915/i915_pci.c |  1 +
 19 files changed, 189 insertions(+), 61 deletions(-)
 rename drivers/gpu/drm/i915/{ => gt}/intel_wopcm.c (86%)
 rename drivers/gpu/drm/i915/{ => gt}/intel_wopcm.h (100%)

-- 
2.37.3



Re: [PATCH v3 10/10] drm/msm/dsi: Prevent signed BPG offsets from bleeding into adjacent bits

2022-10-12 Thread Abhinav Kumar




On 10/9/2022 11:53 AM, Marijn Suijten wrote:

The bpg_offset array contains negative BPG offsets which fill the full 8
bits of a char thanks to two's complement: this however results in those
bits bleeding into the next field when the value is packed into DSC PPS
by the drm_dsc_helper function, which only expects range_bpg_offset to
contain 6-bit wide values.  As a consequence random slices appear
corrupted on-screen (tested on a Sony Tama Akatsuki device with sdm845).

Use AND operators to limit these two's complement values to 6 bits,
similar to the AMD and i915 drivers.

Fixes: b9080324d6ca ("drm/msm/dsi: add support for dsc data")
Signed-off-by: Marijn Suijten 

Reviewed-by: Abhinav Kumar 

---
  drivers/gpu/drm/msm/dsi/dsi_host.c | 6 +-
  1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 46032c576a59..c5c2d70ac27d 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1804,7 +1804,11 @@ static int dsi_populate_dsc_params(struct msm_dsi_host 
*msm_host, struct drm_dsc
for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
dsc->rc_range_params[i].range_min_qp = min_qp[i];
dsc->rc_range_params[i].range_max_qp = max_qp[i];
-   dsc->rc_range_params[i].range_bpg_offset = bpg_offset[i];
+   /*
+* Range BPG Offset contains two's-complement signed values 
that fill
+* 8 bits, yet the registers and DCS PPS field are only 6 bits 
wide.
+*/
+   dsc->rc_range_params[i].range_bpg_offset = bpg_offset[i] & 
DSC_RANGE_BPG_OFFSET_MASK;
}
  
  	dsc->initial_offset = 6144;		/* Not bpp 12 */


Re: [PATCH v3 08/10] drm/msm/dsi: Account for DSC's bits_per_pixel having 4 fractional bits

2022-10-12 Thread Abhinav Kumar




On 10/9/2022 11:53 AM, Marijn Suijten wrote:

drm_dsc_config's bits_per_pixel field holds a fractional value with 4
bits, which all panel drivers should adhere to for
drm_dsc_pps_payload_pack() to generate a valid payload.  All code in the
DSI driver here seems to assume that this field doesn't contain any
fractional bits, hence resulting in the wrong values being computed.
Since none of the calculations leave any room for fractional bits or
seem to indicate any possible area of support, disallow such values
altogether.  calculate_rc_params() in intel_vdsc.c performs an identical
bitshift to get at this integer value.

Fixes: b9080324d6ca ("drm/msm/dsi: add support for dsc data")
Signed-off-by: Marijn Suijten 

Reviewed-by: Abhinav Kumar 

---
  drivers/gpu/drm/msm/dsi/dsi_host.c | 19 ++-
  1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 7e6b7e506ae8..46032c576a59 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -34,7 +34,7 @@
  
  #define DSI_RESET_TOGGLE_DELAY_MS 20
  
-static int dsi_populate_dsc_params(struct drm_dsc_config *dsc);

+static int dsi_populate_dsc_params(struct msm_dsi_host *msm_host, struct 
drm_dsc_config *dsc);
  
  static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)

  {
@@ -909,6 +909,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, 
bool is_bonded_dsi)
u32 va_end = va_start + mode->vdisplay;
u32 hdisplay = mode->hdisplay;
u32 wc;
+   int ret;
  
  	DBG("");
  
@@ -944,7 +945,9 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)

/* we do the calculations for dsc parameters here so that
 * panel can use these parameters
 */
-   dsi_populate_dsc_params(dsc);
+   ret = dsi_populate_dsc_params(msm_host, dsc);
+   if (ret)
+   return;
  
  		/* Divide the display by 3 but keep back/font porch and

 * pulse width same
@@ -1770,9 +1773,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 drm_dsc_config *dsc)

+static int dsi_populate_dsc_params(struct msm_dsi_host *msm_host, struct 
drm_dsc_config *dsc)
  {
int i;
+   u16 bpp = dsc->bits_per_pixel >> 4;
+
+   if (dsc->bits_per_pixel & 0xf) {
+   DRM_DEV_ERROR(_host->pdev->dev, "DSI does not support fractional 
bits_per_pixel\n");
+   return -EINVAL;
+   }
  
  	if (dsc->bits_per_component != 8) {

DRM_DEV_ERROR(_host->pdev->dev, "DSI does not support 
bits_per_component != 8 yet\n");
@@ -1798,8 +1807,8 @@ static int dsi_populate_dsc_params(struct drm_dsc_config 
*dsc)
dsc->rc_range_params[i].range_bpg_offset = bpg_offset[i];
}
  
-	dsc->initial_offset = 6144; /* Not bpp 12 */

-   if (dsc->bits_per_pixel != 8)
+   dsc->initial_offset = 6144;  /* Not bpp 12 */
+   if (bpp != 8)
dsc->initial_offset = 2048;  /* bpp = 12 */
  
  	if (dsc->bits_per_component <= 10)


Re: [PATCH v3 07/10] drm/msm/dsi: Disallow 8 BPC DSC configuration for alternative BPC values

2022-10-12 Thread Abhinav Kumar




On 10/9/2022 11:51 AM, Marijn Suijten wrote:

According to the `/* bpc 8 */` comment below only values for a
bits_per_component of 8 are currently hardcoded in place.  This is
further confirmed by downstream sources [1] containing different
constants for other BPC values (and different initial_offset too,
with an extra dependency on bits_per_pixel).  Prevent future mishaps by
explicitly disallowing any other bits_per_component value until the
right parameters are put in place and tested.

[1]: 
https://git.codelinaro.org/clo/la/platform/vendor/opensource/display-drivers/-/blob/DISPLAY.LA.2.0.r1-08000-WAIPIO.0/msm/sde_dsc_helper.c#L110-139



Seems like a valid kbot error.

https://patchwork.freedesktop.org/patch/506359/#comment_912830


Signed-off-by: Marijn Suijten 
---
  drivers/gpu/drm/msm/dsi/dsi_host.c | 5 +
  1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 68c39debc22f..7e6b7e506ae8 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1774,6 +1774,11 @@ static int dsi_populate_dsc_params(struct drm_dsc_config 
*dsc)
  {
int i;
  
+	if (dsc->bits_per_component != 8) {

+   DRM_DEV_ERROR(_host->pdev->dev, "DSI does not support 
bits_per_component != 8 yet\n");
+   return -EOPNOTSUPP;
+   }
+
dsc->rc_model_size = 8192;
dsc->first_line_bpg_offset = 12;
dsc->rc_edge_factor = 6;


Re: [Freedreno] [PATCH v3 06/10] drm/msm/dsi: Migrate to drm_dsc_compute_rc_parameters()

2022-10-12 Thread Abhinav Kumar




On 10/9/2022 11:50 AM, Marijn Suijten wrote:

As per the FIXME this code is entirely duplicate with what is already
provided inside drm_dsc_compute_rc_parameters(), and it is yet unknown
why this comment was put in place instead of resolved from the get-go.
Not only does it save on duplication, it would have also spared certain
issues.

For example, this code from downstream assumed dsc->bits_per_pixel to
contain an integer value, whereas the upstream drm_dsc_config struct has
it with 4 fractional bits.  drm_dsc_compute_rc_parameters() already
accounts for this feat, and the sole remaining use of
dsc->bits_per_pixel inside dsi_populate_dsc_params() will be addressed
in a separate patch.



This is a nice cleanup! Thanks for doing this. I would actually like to 
move towards the drm_dsc_compute_rc_parameters() API.


But I would like to hold back this change till Vinod clarifies because 
Vinod had mentioned that with drm_dsc_compute_rc_parameters() he was 
seeing a mismatch in the computation of two values.


slice_bpg_offset and the final_offset.

The difference between the upstream drm_dsc_compute_rc_parameters() and 
dsi_populate_dsc_params() causing this was not clear to me from his 
explanation earlier.


So this was left as a to-do item.

I would like this to be re-tested on pixel3 and check if this works for 
vinod. If not, i think its the right time to debug why and not delay 
this more.


Thanks

Abhinav

Fixes: b9080324d6ca ("drm/msm/dsi: add support for dsc data")
Signed-off-by: Marijn Suijten 
---
  drivers/gpu/drm/msm/dsi/dsi_host.c | 64 +++---
  1 file changed, 6 insertions(+), 58 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 83cde4d62b68..68c39debc22f 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -21,6 +21,7 @@
  
  #include 
  
+#include 

  #include 
  
  #include "dsi.h"

@@ -1771,14 +1772,6 @@ static char bpg_offset[DSC_NUM_BUF_RANGES] = {
  
  static int dsi_populate_dsc_params(struct drm_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 data;
-   int final_value, final_scale;
int i;
  
  	dsc->rc_model_size = 8192;

@@ -1804,11 +1797,11 @@ static int dsi_populate_dsc_params(struct 
drm_dsc_config *dsc)
if (dsc->bits_per_pixel != 8)
dsc->initial_offset = 2048;  /* bpp = 12 */
  
-	mux_words_size = 48;		/* bpc == 8/10 */

-   if (dsc->bits_per_component == 12)
-   mux_words_size = 64;
+   if (dsc->bits_per_component <= 10)
+   dsc->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
+   else
+   dsc->mux_word_size = DSC_MUX_WORD_SIZE_12_BPC;
  
-	dsc->mux_word_size = mux_words_size;

dsc->initial_xmit_delay = 512;
dsc->initial_scale_value = 32;
dsc->first_line_bpg_offset = 12;
@@ -1820,52 +1813,7 @@ static int dsi_populate_dsc_params(struct drm_dsc_config 
*dsc)
dsc->rc_quant_incr_limit0 = 11;
dsc->rc_quant_incr_limit1 = 11;
  
-	/* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of

-* params are calculated
-*/
-   groups_per_line = DIV_ROUND_UP(dsc->slice_width, 3);
-   dsc->slice_chunk_size = DIV_ROUND_UP(dsc->slice_width * 
dsc->bits_per_pixel, 8);
-
-   /* rbs-min */
-   min_rate_buffer_size =  dsc->rc_model_size - dsc->initial_offset +
-   dsc->initial_xmit_delay * dsc->bits_per_pixel +
-   groups_per_line * dsc->first_line_bpg_offset;
-
-   hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, dsc->bits_per_pixel);
-
-   dsc->initial_dec_delay = hrd_delay - dsc->initial_xmit_delay;
-
-   dsc->initial_scale_value = 8 * dsc->rc_model_size /
-  (dsc->rc_model_size - 
dsc->initial_offset);
-
-   slice_bits = 8 * dsc->slice_chunk_size * dsc->slice_height;
-
-   groups_total = groups_per_line * dsc->slice_height;
-
-   data = dsc->first_line_bpg_offset * 2048;
-
-   dsc->nfl_bpg_offset = DIV_ROUND_UP(data, (dsc->slice_height - 1));
-
-   pre_num_extra_mux_bits = 3 * (mux_words_size + (4 * 
dsc->bits_per_component + 4) - 2);
-
-   num_extra_mux_bits = pre_num_extra_mux_bits - (mux_words_size -
-((slice_bits - pre_num_extra_mux_bits) % 
mux_words_size));
-
-   data = 2048 * (dsc->rc_model_size - dsc->initial_offset + 
num_extra_mux_bits);
-   dsc->slice_bpg_offset = DIV_ROUND_UP(data, groups_total);
-
-   data = dsc->initial_xmit_delay * dsc->bits_per_pixel;
-   final_value =  dsc->rc_model_size - data + num_extra_mux_bits;
-   dsc->final_offset = final_value;
-
-   final_scale = 8 * dsc->rc_model_size / (dsc->rc_model_size - 

Re: [PATCH v3 05/10] drm/msm/dsi: Appropriately set dsc->mux_word_size based on bpc

2022-10-12 Thread Abhinav Kumar




On 10/9/2022 11:48 AM, Marijn Suijten wrote:

This field is currently unread but will come into effect when duplicated
code below is migrated to call drm_dsc_compute_rc_parameters(), which
uses the bpc-dependent value of the local variable mux_words_size in
much the same way.

The hardcoded constant seems to be a remnant from the `/* bpc 8 */`
comment right above, indicating that this group of field assignments is
applicable to bpc = 8 exclusively and should probably bail out on
different bpc values, until constants for other bpc values are added (or
the current ones are confirmed to be correct across multiple bpc's).



Yes, this seems to hard-code it to 8bpc/10bpc. So your code-change is fine.

Reviewed-by: Abhinav Kumar 

Fixes: b9080324d6ca ("drm/msm/dsi: add support for dsc data")
Signed-off-by: Marijn Suijten 
---
  drivers/gpu/drm/msm/dsi/dsi_host.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index f42794cdd4c1..83cde4d62b68 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1808,6 +1808,7 @@ static int dsi_populate_dsc_params(struct drm_dsc_config 
*dsc)
if (dsc->bits_per_component == 12)
mux_words_size = 64;
  
+	dsc->mux_word_size = mux_words_size;

dsc->initial_xmit_delay = 512;
dsc->initial_scale_value = 32;
dsc->first_line_bpg_offset = 12;
@@ -1818,7 +1819,6 @@ static int dsi_populate_dsc_params(struct drm_dsc_config 
*dsc)
dsc->flatness_max_qp = 12;
dsc->rc_quant_incr_limit0 = 11;
dsc->rc_quant_incr_limit1 = 11;
-   dsc->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


Re: [PATCH -next] drm/nouveau/disp: fix cast removes address space of expression warnings

2022-10-12 Thread Lyude Paul
...oops, totally forgot to actually give you the magic tag so patchwork knows
I reviewed it:

Reviewed-by: Lyude Paul 

On Sat, 2022-09-24 at 17:25 +0800, ruanjinjie wrote:
> When build Linux kernel with 'make C=2', encounter the following warnings:
> 
> ./drivers/gpu/drm/nouveau/dispnv50/disp.c:134:34: warning: cast removes 
> address space '__iomem' of expression
> ./drivers/gpu/drm/nouveau/dispnv50/disp.c:197:34: warning: cast removes 
> address space '__iomem' of expression
> 
> The data type of dmac->_push.mem.object.map.ptr is 'void __iomem *', but
> converted to 'u32 *' directly and cause above warnings, now
> recover their data types to fix these warnings.
> 
> Signed-off-by: ruanjinjie 
> ---
>  drivers/gpu/drm/nouveau/dispnv50/disp.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
> b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> index 33c97d510999..aa94f8e284dd 100644
> --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> @@ -131,7 +131,7 @@ nv50_dmac_kick(struct nvif_push *push)
>  {
>   struct nv50_dmac *dmac = container_of(push, typeof(*dmac), _push);
>  
> - dmac->cur = push->cur - (u32 *)dmac->_push.mem.object.map.ptr;
> + dmac->cur = push->cur - (u32 __iomem *)dmac->_push.mem.object.map.ptr;
>   if (dmac->put != dmac->cur) {
>   /* Push buffer fetches are not coherent with BAR1, we need to 
> ensure
>* writes have been flushed right through to VRAM before 
> writing PUT.
> @@ -194,7 +194,7 @@ nv50_dmac_wait(struct nvif_push *push, u32 size)
>   if (WARN_ON(size > dmac->max))
>   return -EINVAL;
>  
> - dmac->cur = push->cur - (u32 *)dmac->_push.mem.object.map.ptr;
> + dmac->cur = push->cur - (u32 __iomem *)dmac->_push.mem.object.map.ptr;
>   if (dmac->cur + size >= dmac->max) {
>   int ret = nv50_dmac_wind(dmac);
>   if (ret)

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH -next] drm/nouveau/disp: fix cast removes address space of expression warnings

2022-10-12 Thread Lyude Paul
Looks good to me (sorry for the slow response! I think this one just got lost
in the noise). Will push to drm-misc-next in a moment

On Sat, 2022-09-24 at 17:25 +0800, ruanjinjie wrote:
> When build Linux kernel with 'make C=2', encounter the following warnings:
> 
> ./drivers/gpu/drm/nouveau/dispnv50/disp.c:134:34: warning: cast removes 
> address space '__iomem' of expression
> ./drivers/gpu/drm/nouveau/dispnv50/disp.c:197:34: warning: cast removes 
> address space '__iomem' of expression
> 
> The data type of dmac->_push.mem.object.map.ptr is 'void __iomem *', but
> converted to 'u32 *' directly and cause above warnings, now
> recover their data types to fix these warnings.
> 
> Signed-off-by: ruanjinjie 
> ---
>  drivers/gpu/drm/nouveau/dispnv50/disp.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
> b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> index 33c97d510999..aa94f8e284dd 100644
> --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> @@ -131,7 +131,7 @@ nv50_dmac_kick(struct nvif_push *push)
>  {
>   struct nv50_dmac *dmac = container_of(push, typeof(*dmac), _push);
>  
> - dmac->cur = push->cur - (u32 *)dmac->_push.mem.object.map.ptr;
> + dmac->cur = push->cur - (u32 __iomem *)dmac->_push.mem.object.map.ptr;
>   if (dmac->put != dmac->cur) {
>   /* Push buffer fetches are not coherent with BAR1, we need to 
> ensure
>* writes have been flushed right through to VRAM before 
> writing PUT.
> @@ -194,7 +194,7 @@ nv50_dmac_wait(struct nvif_push *push, u32 size)
>   if (WARN_ON(size > dmac->max))
>   return -EINVAL;
>  
> - dmac->cur = push->cur - (u32 *)dmac->_push.mem.object.map.ptr;
> + dmac->cur = push->cur - (u32 __iomem *)dmac->_push.mem.object.map.ptr;
>   if (dmac->cur + size >= dmac->max) {
>   int ret = nv50_dmac_wind(dmac);
>   if (ret)

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



[PATCH v2] drm/panel/panel-sitronix-st7701: Fix RTNI calculation

2022-10-12 Thread Marek Vasut
The RTNI field is multiplied by 16 and incremented by 512 before being
used as the minimum number of pixel clock per horizontal line, hence
it is necessary to subtract those 512 bytes from htotal and then divide
the result by 16 before writing the value into the RTNI field. Fix the
calculation.

Fixes: de2b4917843c ("drm/panel/panel-sitronix-st7701: Infer horizontal pixel 
count from TFT mode")
Signed-off-by: Marek Vasut 
---
Cc: Guido Günther 
Cc: Jagan Teki 
Cc: Laurent Pinchart 
Cc: Linus Walleij 
Cc: Sam Ravnborg 
Cc: Thierry Reding 
---
V2: Clamp the htotal to range 512...1008, so RTNI always fits the bitfield
---
 drivers/gpu/drm/panel/panel-sitronix-st7701.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c 
b/drivers/gpu/drm/panel/panel-sitronix-st7701.c
index c481daa4bbceb..9578f461f5e48 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c
@@ -244,7 +244,7 @@ static void st7701_init_sequence(struct st7701 *st7701)
   DSI_CMD2_BK0_INVSEL_ONES_MASK |
   FIELD_PREP(DSI_CMD2_BK0_INVSEL_NLINV_MASK, desc->nlinv),
   FIELD_PREP(DSI_CMD2_BK0_INVSEL_RTNI_MASK,
- DIV_ROUND_UP(mode->htotal, 16)));
+ (clamp((u32)mode->htotal, 512U, 1008U) - 512) / 
16));
 
/* Command2, BK1 */
ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
-- 
2.35.1



RE: [PATCH v1 3/5] treewide: use get_random_u32() when possible

2022-10-12 Thread David Laight
From: Joe Perches
> Sent: 12 October 2022 20:17
> 
> On Wed, 2022-10-05 at 23:48 +0200, Jason A. Donenfeld wrote:
> > The prandom_u32() function has been a deprecated inline wrapper around
> > get_random_u32() for several releases now, and compiles down to the
> > exact same code. Replace the deprecated wrapper with a direct call to
> > the real function.
> []
> > diff --git a/drivers/infiniband/hw/cxgb4/cm.c 
> > b/drivers/infiniband/hw/cxgb4/cm.c
> []
> > @@ -734,7 +734,7 @@ static int send_connect(struct c4iw_ep *ep)
> >>com.remote_addr;
> > int ret;
> > enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type;
> > -   u32 isn = (prandom_u32() & ~7UL) - 1;
> > +   u32 isn = (get_random_u32() & ~7UL) - 1;
> 
> trivia:
> 
> There are somewhat odd size mismatches here.
> 
> I had to think a tiny bit if random() returned a value from 0 to 7
> and was promoted to a 64 bit value then truncated to 32 bit.
> 
> Perhaps these would be clearer as ~7U and not ~7UL

That makes no difference - the compiler will generate the same code.

The real question is WTF is the code doing?
The '& ~7u' clears the bottom 3 bits.
The '- 1' then sets the bottom 3 bits and decrements the
(random) high bits.

So is the same as get_random_u32() | 7.
But I bet the coder had something else in mind.

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, 
UK
Registration No: 1397386 (Wales)



Re: [RFC/PATCH] backlight: hx8357: prepare to conversion to gpiod API

2022-10-12 Thread Dmitry Torokhov
On Mon, Oct 10, 2022 at 10:36:00PM +0200, Linus Walleij wrote:
> On Thu, Oct 6, 2022 at 12:05 PM Daniel Thompson
>  wrote:
> > On Thu, Oct 06, 2022 at 11:03:15AM +0200, Linus Walleij wrote:
> > > On Tue, Oct 4, 2022 at 10:35 PM Dmitry Torokhov
> > >  wrote:
> > >
> > > > > Dmitry, could you fix this? Just patch away in gpiolib-of.c.
> > > >
> > > > Sure, I'll add a few quirks. I wonder what is the best way to merge
> > > > this? I can create a bunch of IBs to be pulled, or I can send quirks to
> > > > you/Bartosz and once they land send the patches to drivers...
> > >
> > > When I did it I was sufficiently convinced that I was the only one 
> > > patching
> > > the quirks in gpiolib-of.c that merge window so I just included it as
> > > a hunk in the driver patch. If there will be some more patches to that
> > > file I guess some separate patch(es) for gpiolib-of.c is needed, maybe
> > > an immutable branch for those if it becomes a lot.
> >
> > Are renames likely to be a common quirk on the road to libgpiod
> > conversion?
> >
> > I admit I sort of expected it to be common enough that there would be
> > one rename quirk in the code supported by an alphabetized string table.
> > Such a table would certainly still provoke troublesome merges but ones
> > that are trivially resolved.
> 
> Dmitry added a table of sorts, the problems are usually a bit unique
> for each instance of nonstandard DT GPIO bindings, that's why I
> mostly solved it with open coding in gpiolib-of.c.

OK, so I sent out the patch adding "reset-gpios" -> "gpios-reset"
translation quirk to keep compatibility with the legacy names, but
we still need to figure out what to do with incorrect line polarity
in current DTses in tree. Unlike with names we have no indication
if out of tree DTSes specify correct polarity or not, so we can't
reasonably come up with workarounds that are guaranteed to work for
everyone. I see several options:

- the driver could continue ignoring line polarity specified in DTS
  (and use gpiod_set_value_raw()) and hope that they all/will be
  wired in the same way?

- we could fix up in-kernel DTSes, allow flexibility of connection
  in new designs and respect polarity specified in out of tree DTSes,
  but accept that there can be breakages with old DTSes not contributed
  to the mainline or DTSes that were "cached" from an older kernel
  release

- add another quirk forcing "active low" polarity for the legacy
  "gpios-reset" name, which will allow us respecting polarity in
  new "reset-gpios" name.

Thanks.

-- 
Dmitry


Re: [DNM RFC PATCH] drm/msm: Use lowercase hex for !defines

2022-10-12 Thread Rob Clark
On Sat, Oct 8, 2022 at 10:43 AM Konrad Dybcio
 wrote:
>
> drm/msm capitalizes hex numbers rather randomly. Try to unify it.

yeah, there were some different preferences of various patch authors
for shouty HEX vs quiet hex... tbh I prefer the latter, but not really
sure it is worth the noise in git history to change it

BR,
-R

> Generated with:
>
> grep -rEl "\s0x\w*[A-Z]+*\w*" drivers/gpu/drm/msm | \
> xargs sed -i '/define/! s/\s0x\w*[A-Z]+*\w*/\L&/g'
> ---
> I could not find any strict hex capitalization rules for Linux, so
> I'm sending this very loosely, without an S-o-b and as a DNM RFC.
> Funnily enough, this patch somehow broke get_maintainer.pl
>
>  drivers/gpu/drm/msm/adreno/a2xx_gpu.c | 138 +++
>  drivers/gpu/drm/msm/adreno/a4xx_gpu.c | 164 +-
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 126 +++---
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.h |   2 +-
>  drivers/gpu/drm/msm/adreno/a5xx_power.c   | 128 +++---
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c |  26 +--
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.h |   4 +-
>  drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c   |   4 +-
>  drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h   |   2 +-
>  drivers/gpu/drm/msm/adreno/adreno_gpu.h   |  12 +-
>  .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 162 -
>  .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|   4 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c|  26 +--
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c |  10 +-
>  .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   |   8 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c   |  16 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c   |  98 +--
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c   |   2 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c |   2 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |   6 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c |  18 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c  |   2 +-
>  drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c  |  28 +--
>  drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c |   2 +-
>  drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c  |   4 +-
>  drivers/gpu/drm/msm/dp/dp_audio.c |   8 +-
>  drivers/gpu/drm/msm/dp/dp_aux.c   |   2 +-
>  drivers/gpu/drm/msm/dp/dp_catalog.c   |  14 +-
>  drivers/gpu/drm/msm/dp/dp_ctrl.c  |   4 +-
>  drivers/gpu/drm/msm/dp/dp_display.c   |   2 +-
>  drivers/gpu/drm/msm/dp/dp_link.c  |  10 +-
>  drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c|   4 +-
>  drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c |   2 +-
>  drivers/gpu/drm/msm/hdmi/hdmi.c   |   4 +-
>  drivers/gpu/drm/msm/hdmi/hdmi_hdcp.c  |  20 +--
>  drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c  |  22 +--
>  36 files changed, 543 insertions(+), 543 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c
> index 6c9a747eb4ad..f207588218c6 100644
> --- a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c
> @@ -236,7 +236,7 @@ static int a2xx_hw_init(struct msm_gpu *gpu)
> for (i = 1; i < len; i++)
> gpu_write(gpu, REG_A2XX_CP_PFP_UCODE_DATA, ptr[i]);
>
> -   gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x000C0804);
> +   gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x000c0804);
>
> /* clear ME_HALT to start micro engine */
> gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
> @@ -335,90 +335,90 @@ static irqreturn_t a2xx_irq(struct msm_gpu *gpu)
>  }
>
>  static const unsigned int a200_registers[] = {
> -   0x, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
> -   0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9,
> -   0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7,
> -   0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5,
> -   0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444,
> -   0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B,
> -   0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0,
> -   0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614,
> -   0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A43, 0x0A45, 0x0A45,
> -   0x0A4E, 0x0A4F, 0x0C2C, 0x0C2C, 0x0C30, 0x0C30, 0x0C38, 0x0C3C,
> -   0x0C40, 0x0C40, 0x0C44, 0x0C44, 0x0C80, 0x0C86, 0x0C88, 0x0C94,
> -   0x0C99, 0x0C9A, 0x0CA4, 0x0CA5, 0x0D00, 0x0D03, 0x0D06, 0x0D06,
> -   0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 0x0DC8, 0x0DD4,
> -   0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 0x0E17, 0x0E1E,
> -   0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 0x0ED4, 0x0ED7,
> -   0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x0F0C, 0x0F0C, 0x0F0E, 0x0F12,
> -   0x0F26, 0x0F2A, 0x0F2C, 0x0F2C, 0x2000, 0x2002, 0x2006, 0x200F,
> -   0x2080, 0x2082, 0x2100, 0x2109, 0x210C, 0x2114, 0x2180, 

[PATCH] fbdev: MIPS supports iomem addresses

2022-10-12 Thread Kees Cook
Add MIPS to fb_* helpers list for iomem addresses. This silences Sparse
warnings about lacking __iomem address space casts:

drivers/video/fbdev/pvr2fb.c:800:9: sparse: sparse: incorrect type in argument 
1 (different address spaces)
drivers/video/fbdev/pvr2fb.c:800:9: sparse: expected void const *
drivers/video/fbdev/pvr2fb.c:800:9: sparse: got char [noderef] __iomem 
*screen_base

Reported-by: kernel test robot 
Link: https://lore.kernel.org/lkml/202210100209.tr2iqbqk-...@intel.com/
Cc: Helge Deller 
Cc: linux-fb...@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Kees Cook 
---
 include/linux/fb.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/fb.h b/include/linux/fb.h
index 07fcd0e56682..3822734a38c7 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -555,7 +555,7 @@ static inline struct apertures_struct 
*alloc_apertures(unsigned int max_num) {
 
 #elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) ||
\
defined(__hppa__) || defined(__sh__) || defined(__powerpc__) || \
-   defined(__arm__) || defined(__aarch64__)
+   defined(__arm__) || defined(__aarch64__) || defined(__mips__)
 
 #define fb_readb __raw_readb
 #define fb_readw __raw_readw
-- 
2.34.1



Re: [PATCH v1 3/5] treewide: use get_random_u32() when possible

2022-10-12 Thread Joe Perches
On Wed, 2022-10-05 at 23:48 +0200, Jason A. Donenfeld wrote:
> The prandom_u32() function has been a deprecated inline wrapper around
> get_random_u32() for several releases now, and compiles down to the
> exact same code. Replace the deprecated wrapper with a direct call to
> the real function.
[]
> diff --git a/drivers/infiniband/hw/cxgb4/cm.c 
> b/drivers/infiniband/hw/cxgb4/cm.c
[]
> @@ -734,7 +734,7 @@ static int send_connect(struct c4iw_ep *ep)
>  >com.remote_addr;
>   int ret;
>   enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type;
> - u32 isn = (prandom_u32() & ~7UL) - 1;
> + u32 isn = (get_random_u32() & ~7UL) - 1;

trivia:

There are somewhat odd size mismatches here.

I had to think a tiny bit if random() returned a value from 0 to 7
and was promoted to a 64 bit value then truncated to 32 bit.

Perhaps these would be clearer as ~7U and not ~7UL

>   struct net_device *netdev;
>   u64 params;
>  
> @@ -2469,7 +2469,7 @@ static int accept_cr(struct c4iw_ep *ep, struct sk_buff 
> *skb,
>   }
>  
>   if (!is_t4(adapter_type)) {
> - u32 isn = (prandom_u32() & ~7UL) - 1;
> + u32 isn = (get_random_u32() & ~7UL) - 1;

etc...

drivers/infiniband/hw/cxgb4/cm.c:   u32 isn = (prandom_u32() & ~7UL) - 1;
drivers/infiniband/hw/cxgb4/cm.c:   u32 isn = (prandom_u32() & 
~7UL) - 1;
drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c:rpl5->iss = 
cpu_to_be32((prandom_u32() & ~7UL) - 1);
drivers/scsi/cxgbi/cxgb4i/cxgb4i.c: u32 isn = (prandom_u32() & 
~7UL) - 1;
drivers/scsi/cxgbi/cxgb4i/cxgb4i.c: u32 isn = (prandom_u32() & 
~7UL) - 1;
drivers/target/iscsi/cxgbit/cxgbit_cm.c:rpl5->iss = 
cpu_to_be32((prandom_u32() & ~7UL) - 1);



[PATCH v3] drm/mediatek: Add AFBC support to Mediatek DRM driver

2022-10-12 Thread Justin Green
Tested on MT8195 and confirmed both correct video output and improved DRAM
bandwidth performance.

v3:
* Replaced pitch bitshift math with union based approach.
* Refactored overlay register writes to shared code between non-AFBC and
  AFBC.
* Minor code cleanups.

v2:
* Marked mtk_ovl_set_afbc as static.
* Reflowed some lines to fit column limit.

Signed-off-by: Justin Green 
---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c  | 90 +++-
 drivers/gpu/drm/mediatek/mtk_drm_plane.c | 37 +-
 drivers/gpu/drm/mediatek/mtk_drm_plane.h |  8 +++
 3 files changed, 131 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c 
b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 002b0f6cae1a..3f89b5f5064f 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -29,17 +29,24 @@
 #define DISP_REG_OVL_DATAPATH_CON  0x0024
 #define OVL_LAYER_SMI_ID_ENBIT(0)
 #define OVL_BGCLR_SEL_IN   BIT(2)
+#define OVL_LAYER_AFBC_EN(n)   BIT(4+n)
 #define DISP_REG_OVL_ROI_BGCLR 0x0028
 #define DISP_REG_OVL_SRC_CON   0x002c
 #define DISP_REG_OVL_CON(n)(0x0030 + 0x20 * (n))
 #define DISP_REG_OVL_SRC_SIZE(n)   (0x0038 + 0x20 * (n))
 #define DISP_REG_OVL_OFFSET(n) (0x003c + 0x20 * (n))
+#define DISP_REG_OVL_PITCH_MSB(n)  (0x0040 + 0x20 * (n))
+#define OVL_PITCH_MSB_2ND_SUBBUF   BIT(16)
+#define OVL_PITCH_MSB_YUV_TRANSBIT(20)
 #define DISP_REG_OVL_PITCH(n)  (0x0044 + 0x20 * (n))
+#define DISP_REG_OVL_CLIP(n)   (0x004c + 0x20 * (n))
 #define DISP_REG_OVL_RDMA_CTRL(n)  (0x00c0 + 0x20 * (n))
 #define DISP_REG_OVL_RDMA_GMC(n)   (0x00c8 + 0x20 * (n))
 #define DISP_REG_OVL_ADDR_MT2701   0x0040
 #define DISP_REG_OVL_ADDR_MT8173   0x0f40
 #define DISP_REG_OVL_ADDR(ovl, n)  ((ovl)->data->addr + 0x20 * (n))
+#define DISP_REG_OVL_HDR_ADDR(ovl, n)  ((ovl)->data->addr + 0x20 * (n) 
+ 0x04)
+#define DISP_REG_OVL_HDR_PITCH(ovl, n) ((ovl)->data->addr + 0x20 * (n) 
+ 0x08)
 
 #define GMC_THRESHOLD_BITS 16
 #define GMC_THRESHOLD_HIGH ((1 << GMC_THRESHOLD_BITS) / 4)
@@ -67,6 +74,7 @@ struct mtk_disp_ovl_data {
unsigned int layer_nr;
bool fmt_rgb565_is_0;
bool smi_id_en;
+   bool supports_afbc;
 };
 
 /*
@@ -172,7 +180,22 @@ void mtk_ovl_stop(struct device *dev)
reg = reg & ~OVL_LAYER_SMI_ID_EN;
writel_relaxed(reg, ovl->regs + DISP_REG_OVL_DATAPATH_CON);
}
+}
+
+static void mtk_ovl_set_afbc(struct device *dev, struct cmdq_pkt *cmdq_pkt,
+int idx, bool enabled)
+{
+   struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
+   unsigned int reg;
 
+   reg = readl(ovl->regs + DISP_REG_OVL_DATAPATH_CON);
+   if (enabled)
+   reg = reg | OVL_LAYER_AFBC_EN(idx);
+   else
+   reg = reg & ~OVL_LAYER_AFBC_EN(idx);
+
+   mtk_ddp_write_relaxed(cmdq_pkt, reg, >cmdq_reg,
+ ovl->regs, DISP_REG_OVL_DATAPATH_CON);
 }
 
 void mtk_ovl_config(struct device *dev, unsigned int w,
@@ -226,6 +249,32 @@ int mtk_ovl_layer_check(struct device *dev, unsigned int 
idx,
if (state->fb->format->is_yuv && rotation != 0)
return -EINVAL;
 
+   if (state->fb->modifier) {
+   unsigned long long modifier;
+   unsigned int fourcc;
+   struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
+
+   if (!ovl->data->supports_afbc)
+   return -EINVAL;
+
+   modifier = state->fb->modifier;
+
+   if (modifier != 
DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
+   AFBC_FORMAT_MOD_SPLIT |
+   AFBC_FORMAT_MOD_SPARSE))
+   return -EINVAL;
+
+   fourcc = state->fb->format->format;
+   if (fourcc != DRM_FORMAT_BGRA &&
+   fourcc != DRM_FORMAT_ABGR &&
+   fourcc != DRM_FORMAT_ARGB &&
+   fourcc != DRM_FORMAT_XRGB &&
+   fourcc != DRM_FORMAT_XBGR &&
+   fourcc != DRM_FORMAT_RGB888 &&
+   fourcc != DRM_FORMAT_BGR888)
+   return -EINVAL;
+   }
+
state->rotation = rotation;
 
return 0;
@@ -310,11 +359,23 @@ void mtk_ovl_layer_config(struct device *dev, unsigned 
int idx,
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
struct mtk_plane_pending_state *pending = >pending;
unsigned int addr = pending->addr;
-   unsigned int pitch = pending->pitch & 0x;
+   unsigned int 

Re: [PATCH 0/3] Add _PICK_EVEN_RANGES

2022-10-12 Thread Lucas De Marchi

On Wed, Oct 12, 2022 at 11:51:48AM +0300, Jani Nikula wrote:

On Tue, 11 Oct 2022, Lucas De Marchi  wrote:

Add a new macro, _PICK_EVEN_RANGES, that supports using 2 address
ranges. This should cover most of our needs for _MMIO_PLL3 and such.
To show what is achieved with the new macro, convert some PLL-related
macros to use it instead of _MMIO_PLL3.


While there's nothing particularly wrong about the solution when looked
at in isolation, I do have pretty strong reservations on the whole.

We have:

1) _PICK_EVEN() used in _PIPE() and friends

2) _PICK() used in _MMIO_PIPE3() and friends

3) ->pipe_offsets[] etc. adjustment used in _MMIO_PIPE2() and friends

4) ->ddi_index[] mapping proposed in [1]

5) _PICK_EVEN_RANGES() proposed here

Originally we only had the first one, when the hardware was
simpler. Every single addition since then made sense at the time, but if
we add 4 & 5 to the mix, I think it's just too many options.

I think it's time to take a step back and figure out if there's a more
generic approach that could be used.


true... I actually see this as replacing most of the uses of _PICK()
and giving and extra benefit of removing the worry we are doing
out-of-bounds array access. It also allows to more easily move ranges
for new platforms, which is my intention here.

So I think that we could have something like this if changing it to
something else means a bigger refactor. Talking about a big refactor, I
still think my series from a few years back would make sense:

drm/i915/display: start description-based ddi initialization
(https://lore.kernel.org/all/20191223195850.25997-1-lucas.demar...@intel.com/)

I think that got stalled due to initialization in the intel_ddi.c trying
too much to group together the if/else ladder. But the overall intention
of the patch series I believe is still valid today:

(...) create a table-based initialization approach in
which I keep the useful indexes for each platform: these indexes work
similarly to what we have on the pll part. "enum port" is mostly a
"driver thing" and when all the conversions take place, it would allow
us to stop using the port as indexes to register or register bits. "enum
tc_port", "enum phy", etc are not meaningful numbers from the spec POV
and change with every other platform.

+Bala who apparently is going to a similar approach in the ddi_index
approach.

Other possible approaches hat come to mind (just dumping some thoughts,
with no actual code/poc):

1) Inside display strut we have:

struct {
u8 version;
union {
struct {
i915_reg_t foo;
i915_reg_t bar;
i915_reg_t bla;
} v1;
struct {
i915_reg_t xyz;
i915_reg_t ijk;
} v2;
}
} regs;

instead of vesion it could be the "first platform to use it" like we
currently have. Those registers would then be initialized during module
bind and then we stop doing these conversions to map a platform to a
register offset.  It still needs some per-platform change for the
bitfields though.

idea would be then to enforce using the right struct inside the union by
splitting the code in differen compilation units. One platform can
evolve from the other with the same compilation unit as long as it is
backward-compatible, i.e. we can add more registers, change offsets,
etc. But if the HW interface completely changes, it would need to use a
different version.

2) Looking around what other teams do. In mesa the registers are actually
maintained in a xml. Example: gen12.xml


  
  


In code it's used like this:

reg.HZDepthTestLEGEOptimizationDisable = true;

3) Kind of going in the same direction, but more in the kernel side. Maybe
switching to regmap?


I think one of the things that block this kind of refactors is having to
bring them back to all the previous platforms. Maybe going back only
until HAS_DDI() would be a good approach. Or maybe even spliting it on
DISPLAY_VER == 12?  That might help more radical changes.


Lucas De Marchi




BR,
Jani.


[1] https://patchwork.freedesktop.org/series/108833/

--
Jani Nikula, Intel Open Source Graphics Center


[PATCH] drm/i915/slpc: Use platform limits for min/max frequency

2022-10-12 Thread Vinay Belgaumkar
GuC will set the min/max frequencies to theoretical max on
ATS-M. This will break kernel ABI, so limit min/max frequency
to RP0(platform max) instead.

Also modify the SLPC selftest to update the min frequency
when we have a server part so that we can iterate between
platform min and max.

Signed-off-by: Vinay Belgaumkar 
---
 drivers/gpu/drm/i915/gt/selftest_slpc.c   | 40 +--
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c   | 29 ++
 .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h |  3 ++
 3 files changed, 60 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c 
b/drivers/gpu/drm/i915/gt/selftest_slpc.c
index 4c6e9257e593..1f84362af737 100644
--- a/drivers/gpu/drm/i915/gt/selftest_slpc.c
+++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c
@@ -234,6 +234,7 @@ static int run_test(struct intel_gt *gt, int test_type)
enum intel_engine_id id;
struct igt_spinner spin;
u32 slpc_min_freq, slpc_max_freq;
+   u32 saved_min_freq;
int err = 0;
 
if (!intel_uc_uses_guc_slpc(>uc))
@@ -252,20 +253,35 @@ static int run_test(struct intel_gt *gt, int test_type)
return -EIO;
}
 
-   /*
-* FIXME: With efficient frequency enabled, GuC can request
-* frequencies higher than the SLPC max. While this is fixed
-* in GuC, we level set these tests with RPn as min.
-*/
-   err = slpc_set_min_freq(slpc, slpc->min_freq);
-   if (err)
-   return err;
-
if (slpc->min_freq == slpc->rp0_freq) {
-   pr_err("Min/Max are fused to the same value\n");
-   return -EINVAL;
+   /* Servers will have min/max clamped to RP0 */
+   if (slpc->min_is_rpmax) {
+   err = slpc_set_min_freq(slpc, slpc->min_freq);
+   if (err) {
+   pr_err("Unable to update min freq on server 
part");
+   return err;
+   }
+
+   } else {
+   pr_err("Min/Max are fused to the same value\n");
+   return -EINVAL;
+   }
+   } else {
+   /*
+* FIXME: With efficient frequency enabled, GuC can request
+* frequencies higher than the SLPC max. While this is fixed
+* in GuC, we level set these tests with RPn as min.
+*/
+   err = slpc_set_min_freq(slpc, slpc->min_freq);
+   if (err)
+   return err;
}
 
+   saved_min_freq = slpc_min_freq;
+
+   /* New temp min freq = RPn */
+   slpc_min_freq = slpc->min_freq;
+
intel_gt_pm_wait_for_idle(gt);
intel_gt_pm_get(gt);
for_each_engine(engine, gt, id) {
@@ -347,7 +363,7 @@ static int run_test(struct intel_gt *gt, int test_type)
 
/* Restore min/max frequencies */
slpc_set_max_freq(slpc, slpc_max_freq);
-   slpc_set_min_freq(slpc, slpc_min_freq);
+   slpc_set_min_freq(slpc, saved_min_freq);
 
if (igt_flush_test(gt->i915))
err = -EIO;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
index fdd895f73f9f..11613d373a49 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -263,6 +263,7 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
 
slpc->max_freq_softlimit = 0;
slpc->min_freq_softlimit = 0;
+   slpc->min_is_rpmax = false;
 
slpc->boost_freq = 0;
atomic_set(>num_waiters, 0);
@@ -588,6 +589,31 @@ static int slpc_set_softlimits(struct intel_guc_slpc *slpc)
return 0;
 }
 
+static bool is_slpc_min_freq_rpmax(struct intel_guc_slpc *slpc)
+{
+   int slpc_min_freq;
+
+   if (intel_guc_slpc_get_min_freq(slpc, _min_freq))
+   return false;
+
+   if (slpc_min_freq > slpc->rp0_freq)
+   return true;
+   else
+   return false;
+}
+
+static void update_server_min_softlimit(struct intel_guc_slpc *slpc)
+{
+   /* For server parts, SLPC min will be at RPMax.
+* Use min softlimit to clamp it to RP0 instead.
+*/
+   if (is_slpc_min_freq_rpmax(slpc) &&
+   !slpc->min_freq_softlimit) {
+   slpc->min_is_rpmax = true;
+   slpc->min_freq_softlimit = slpc->rp0_freq;
+   }
+}
+
 static int slpc_use_fused_rp0(struct intel_guc_slpc *slpc)
 {
/* Force SLPC to used platform rp0 */
@@ -647,6 +673,9 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
 
slpc_get_rp_values(slpc);
 
+   /* Handle the case where min=max=RPmax */
+   update_server_min_softlimit(slpc);
+
/* Set SLPC max limit to RP0 */
ret = slpc_use_fused_rp0(slpc);
if (unlikely(ret)) {
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h 

Re: [PATCH] drm/edid/firmware: stop using throwaway platform device

2022-10-12 Thread Matthieu CHARETTE
By crash, I mean that an error is returned here: 
https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux.git/+/refs/heads/master/drivers/gpu/drm/drm_edid_load.c#195
I don't really know what happens next, but on my machine the built-in 
screen and the external remains dark. Also the kernel seems to freeze. 
I suspect a kernel panic, but I'm not sure. Anyway, the error is 
definitely not well handled, and a fix would be great.
Also, request_firmware() will crash if called for the first time on the 
resume path because the file system isn't reachable on the resume 
process. And no cache is available for this firmware. So I guess that 
in this case, request_firmware() returns an error.
Suspend-plug-resume case is not my priority nether as long as it 
doesn't make the system crash (Which is currently the case).


On Wed, Oct 12 2022 at 11:25:59 AM +0300, Jani Nikula 
 wrote:
On Tue, 11 Oct 2022, Matthieu CHARETTE  
wrote:

 Currently the EDID is requested during the resume. But since it's
 requested too early, this means before the filesystem is mounted, 
the
 firmware request fails. This make the DRM driver crash when 
resuming.
 This kind of issue should be prevented by the firmware caching 
process
 which cache every firmware requested for the next resume. But since 
we

 are using a temporary device, the firmware isn't cached on suspend
 since the device doesn't work anymore.
 When using a non temporary device to get the EDID, the firmware will
 be cached on suspend for the next resume. So requesting the firmware
 during resume will succeed.
 But if the firmware has never been requested since the boot, this
 means that the monitor isn't plugged since the boot. The kernel will
 not be caching the EDID. So if we plug the monitor while the machine
 is suspended. The resume will fail to load the firmware. And the DRM
 driver will crash.
 So basically, your fix should solve the issue except for the case
 where the monitor hasn't been plugged since boot and is plugged 
while

 the machine is suspended.
 I hope I was clear. Tell me if I wasn't. I'm not really good at 
explaining.


That was a pretty good explanation. The only thing I'm missing is what
the failure mode is exactly when you claim the driver will crash. Why
would request_firmware() "crash" if called for the first time on the
resume path?

I'm not sure I care much about not being able to load the firmware 
EDID

in the suspend-plug-resume case (as this can be remedied with a
subsequent modeset), but obviously any errors need to be handled
gracefully, without crashing.

BR,
Jani.


--
Jani Nikula, Intel Open Source Graphics Center





[PATCH 2/3] drm/bridge: it6505: Setup links in it6505_irq_hpd

2022-10-12 Thread Pin-yen Lin
Move the DPCD read and link setup steps to HPD IRQ handler to remove
an unnecessary dependency between .detect callback and the HPD IRQ
handler before registering it6505 as a DRM bridge. This is safe because
there is always a .detect call after each HPD IRQ handler triggered by
the drm_helper_hpd_irq_event call.

Signed-off-by: Pin-yen Lin 
---

 drivers/gpu/drm/bridge/ite-it6505.c | 74 +++--
 1 file changed, 29 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ite-it6505.c 
b/drivers/gpu/drm/bridge/ite-it6505.c
index f7f6c3e20fae..cf94e44ec73a 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -725,28 +725,6 @@ static void it6505_calc_video_info(struct it6505 *it6505)
 DRM_MODE_ARG(>video_info));
 }
 
-static int it6505_drm_dp_link_probe(struct drm_dp_aux *aux,
-   struct it6505_drm_dp_link *link)
-{
-   u8 values[3];
-   int err;
-
-   memset(link, 0, sizeof(*link));
-
-   err = drm_dp_dpcd_read(aux, DP_DPCD_REV, values, sizeof(values));
-   if (err < 0)
-   return err;
-
-   link->revision = values[0];
-   link->rate = drm_dp_bw_code_to_link_rate(values[1]);
-   link->num_lanes = values[2] & DP_MAX_LANE_COUNT_MASK;
-
-   if (values[2] & DP_ENHANCED_FRAME_CAP)
-   link->capabilities = DP_ENHANCED_FRAME_CAP;
-
-   return 0;
-}
-
 static int it6505_drm_dp_link_set_power(struct drm_dp_aux *aux,
struct it6505_drm_dp_link *link,
u8 mode)
@@ -1456,11 +1434,19 @@ static void it6505_parse_link_capabilities(struct 
it6505 *it6505)
int bcaps;
 
if (it6505->dpcd[0] == 0) {
-   it6505_aux_on(it6505);
-   it6505_get_dpcd(it6505, DP_DPCD_REV, it6505->dpcd,
-   ARRAY_SIZE(it6505->dpcd));
+   dev_err(dev, "DPCD is not initialized");
+   return;
}
 
+   memset(link, 0, sizeof(*link));
+
+   link->revision = it6505->dpcd[0];
+   link->rate = drm_dp_bw_code_to_link_rate(it6505->dpcd[1]);
+   link->num_lanes = it6505->dpcd[2] & DP_MAX_LANE_COUNT_MASK;
+
+   if (it6505->dpcd[2] & DP_ENHANCED_FRAME_CAP)
+   link->capabilities = DP_ENHANCED_FRAME_CAP;
+
DRM_DEV_DEBUG_DRIVER(dev, "DPCD Rev.: %d.%d",
 link->revision >> 4, link->revision & 0x0F);
 
@@ -2328,14 +2314,21 @@ static void it6505_irq_hpd(struct it6505 *it6505)
DRM_DEV_DEBUG_DRIVER(dev, "hpd change interrupt, change to %s",
 it6505->hpd_state ? "high" : "low");
 
-   if (it6505->bridge.dev)
-   drm_helper_hpd_irq_event(it6505->bridge.dev);
-   DRM_DEV_DEBUG_DRIVER(dev, "it6505->sink_count: %d",
-it6505->sink_count);
-
if (it6505->hpd_state) {
wait_for_completion_timeout(>wait_edid_complete,
msecs_to_jiffies(6000));
+   it6505_aux_on(it6505);
+   if (it6505->dpcd[0] == 0) {
+   it6505_get_dpcd(it6505, DP_DPCD_REV, it6505->dpcd,
+   ARRAY_SIZE(it6505->dpcd));
+   it6505_variable_config(it6505);
+   it6505_parse_link_capabilities(it6505);
+   }
+   it6505->auto_train_retry = AUTO_TRAIN_RETRY;
+
+   DRM_DEV_DEBUG_DRIVER(dev, "it6505->sink_count: %d",
+it6505->sink_count);
+
it6505_lane_termination_on(it6505);
it6505_lane_power_on(it6505);
 
@@ -2363,6 +2356,9 @@ static void it6505_irq_hpd(struct it6505 *it6505)
it6505_lane_off(it6505);
it6505_link_reset_step_train(it6505);
}
+
+   if (it6505->bridge.dev)
+   drm_helper_hpd_irq_event(it6505->bridge.dev);
 }
 
 static void it6505_irq_hpd_irq(struct it6505 *it6505)
@@ -2625,26 +2621,14 @@ static enum drm_connector_status it6505_detect(struct 
it6505 *it6505)
goto unlock;
 
if (it6505->enable_drv_hold) {
-   status = it6505_get_sink_hpd_status(it6505) ?
-   connector_status_connected :
-   connector_status_disconnected;
+   status = it6505->hpd_state ?  connector_status_connected :
+ connector_status_disconnected;
goto unlock;
}
 
-   if (it6505_get_sink_hpd_status(it6505)) {
-   it6505_aux_on(it6505);
-   it6505_drm_dp_link_probe(>aux, >link);
+   if (it6505->hpd_state) {
it6505_drm_dp_link_set_power(>aux, >link,
 DP_SET_POWER_D0);
-   it6505->auto_train_retry = 

[PATCH 3/3] drm/bridge: it6505: Improve synchronization between extcon subsystem

2022-10-12 Thread Pin-yen Lin
Originally, the it6505 relies on a short sleep in the IRQ handler and a
long sleep to make sure it6505->lane_swap and it6505->lane_count is
configured in it6505_extcon_work and it6505_detect, respectively.

Use completion and additional DPCD read to remove the unnecessary waits,
and use a different lock for it6505_extcon_work and the threaded IRQ
handler because they no longer need to run exclusively.

The wait time of the completion is usually less than 10ms in local
experiments, but leave it larger here just in case.

Signed-off-by: Pin-yen Lin 
---

 drivers/gpu/drm/bridge/ite-it6505.c | 19 +++
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ite-it6505.c 
b/drivers/gpu/drm/bridge/ite-it6505.c
index cf94e44ec73a..52515b43171c 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -412,6 +412,7 @@ struct it6505 {
 * Mutex protects extcon and interrupt functions from interfering
 * each other.
 */
+   struct mutex irq_lock;
struct mutex extcon_lock;
struct mutex mode_lock; /* used to bridge_detect */
struct mutex aux_lock; /* used to aux data transfers */
@@ -440,7 +441,7 @@ struct it6505 {
enum hdcp_state hdcp_status;
struct delayed_work hdcp_work;
struct work_struct hdcp_wait_ksv_list;
-   struct completion wait_edid_complete;
+   struct completion extcon_completion;
u8 auto_train_retry;
bool hdcp_desired;
bool is_repeater;
@@ -2315,8 +2316,8 @@ static void it6505_irq_hpd(struct it6505 *it6505)
 it6505->hpd_state ? "high" : "low");
 
if (it6505->hpd_state) {
-   wait_for_completion_timeout(>wait_edid_complete,
-   msecs_to_jiffies(6000));
+   wait_for_completion_timeout(>extcon_completion,
+   msecs_to_jiffies(1000));
it6505_aux_on(it6505);
if (it6505->dpcd[0] == 0) {
it6505_get_dpcd(it6505, DP_DPCD_REV, it6505->dpcd,
@@ -2328,7 +2329,6 @@ static void it6505_irq_hpd(struct it6505 *it6505)
 
DRM_DEV_DEBUG_DRIVER(dev, "it6505->sink_count: %d",
 it6505->sink_count);
-
it6505_lane_termination_on(it6505);
it6505_lane_power_on(it6505);
 
@@ -2487,8 +2487,7 @@ static irqreturn_t it6505_int_threaded_handler(int 
unused, void *data)
};
int int_status[3], i;
 
-   msleep(100);
-   mutex_lock(>extcon_lock);
+   mutex_lock(>irq_lock);
 
if (it6505->enable_drv_hold || !it6505->powered)
goto unlock;
@@ -2518,7 +2517,7 @@ static irqreturn_t it6505_int_threaded_handler(int 
unused, void *data)
}
 
 unlock:
-   mutex_unlock(>extcon_lock);
+   mutex_unlock(>irq_lock);
 
return IRQ_HANDLED;
 }
@@ -2695,9 +2694,12 @@ static void it6505_extcon_work(struct work_struct *work)
 */
if (ret)
it6505_poweron(it6505);
+
+   complete_all(>extcon_completion);
} else {
DRM_DEV_DEBUG_DRIVER(dev, "start to power off");
pm_runtime_put_sync(dev);
+   reinit_completion(>extcon_completion);
 
drm_helper_hpd_irq_event(it6505->bridge.dev);
memset(it6505->dpcd, 0, sizeof(it6505->dpcd));
@@ -3268,6 +3270,7 @@ static int it6505_i2c_probe(struct i2c_client *client,
if (!it6505)
return -ENOMEM;
 
+   mutex_init(>irq_lock);
mutex_init(>extcon_lock);
mutex_init(>mode_lock);
mutex_init(>aux_lock);
@@ -3323,7 +3326,7 @@ static int it6505_i2c_probe(struct i2c_client *client,
INIT_WORK(>link_works, it6505_link_training_work);
INIT_WORK(>hdcp_wait_ksv_list, it6505_hdcp_wait_ksv_list);
INIT_DELAYED_WORK(>hdcp_work, it6505_hdcp_work);
-   init_completion(>wait_edid_complete);
+   init_completion(>extcon_completion);
memset(it6505->dpcd, 0, sizeof(it6505->dpcd));
it6505->powered = false;
it6505->enable_drv_hold = DEFAULT_DRV_HOLD;
-- 
2.38.0.rc1.362.ged0d419d3c-goog



[PATCH 1/3] drm/bridge: it6505: Initialize AUX channel in it6505_i2c_probe

2022-10-12 Thread Pin-yen Lin
During device boot, the HPD interrupt could be triggered before the DRM
subsystem registers it6505 as a DRM bridge. In such cases, the driver
tries to access AUX channel and causes NULL pointer dereference.
Initializing the AUX channel earlier to prevent such error.

Fixes: b5c84a9edcd4 ("drm/bridge: add it6505 driver")
Signed-off-by: Pin-yen Lin 
---

 drivers/gpu/drm/bridge/ite-it6505.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ite-it6505.c 
b/drivers/gpu/drm/bridge/ite-it6505.c
index a4302492cf8d..f7f6c3e20fae 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -2871,10 +2871,7 @@ static int it6505_bridge_attach(struct drm_bridge 
*bridge,
}
 
/* Register aux channel */
-   it6505->aux.name = "DP-AUX";
-   it6505->aux.dev = dev;
it6505->aux.drm_dev = bridge->dev;
-   it6505->aux.transfer = it6505_aux_transfer;
 
ret = drm_dp_aux_register(>aux);
 
@@ -3354,6 +3351,11 @@ static int it6505_i2c_probe(struct i2c_client *client,
debugfs_init(it6505);
pm_runtime_enable(dev);
 
+   it6505->aux.name = "DP-AUX";
+   it6505->aux.dev = dev;
+   it6505->aux.transfer = it6505_aux_transfer;
+   drm_dp_aux_init(>aux);
+
it6505->bridge.funcs = _bridge_funcs;
it6505->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;
it6505->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
-- 
2.38.0.rc1.362.ged0d419d3c-goog



[PATCH 0/3] Clean up it6505 driver and improve synchronization

2022-10-12 Thread Pin-yen Lin
The main purpose of this series is to improve the synchronizations of
it6505 driver. The first two patches are required for the third one, but
they alone can be clean ups to the driver.


Pin-yen Lin (3):
  drm/bridge: it6505: Initialize AUX channel in it6505_i2c_probe
  drm/bridge: it6505: Setup links in it6505_irq_hpd
  drm/bridge: it6505: Improve synchronization between extcon subsystem

 drivers/gpu/drm/bridge/ite-it6505.c | 99 +
 1 file changed, 44 insertions(+), 55 deletions(-)

-- 
2.38.0.rc1.362.ged0d419d3c-goog



[pull] amdgpu drm-fixes-6.1

2022-10-12 Thread Alex Deucher
Hi Dave, Daniel,

Fixes for 6.1.

The following changes since commit 65898687cf7392c372ea8d04a88617e2cb794465:

  Merge tag 'amd-drm-next-6.1-2022-09-30' of 
https://gitlab.freedesktop.org/agd5f/linux into drm-next (2022-10-04 09:42:24 
+1000)

are available in the Git repository at:

  https://gitlab.freedesktop.org/agd5f/linux.git 
tags/amd-drm-fixes-6.1-2022-10-12

for you to fetch changes up to 0811b9e4530d7c46542a8993ce6b725d042c6154:

  drm/amd/display: Add HUBP surface flip interrupt handler (2022-10-12 11:27:41 
-0400)


amd-drm-fixes-6.1-2022-10-12:

amdgpu:
- DC mutex fix
- DC SubVP fixes
- DCN 3.2.x fixes
- DCN 3.1.x fixes
- SDMA 6.x fixes
- Enable DPIA for 3.1.4
- VRR fixes
- VRAM BO swapping fix
- Revert dirty fb helper change
- SR-IOV suspend/resume fixes
- Work around GCC array bounds check fail warning
- UMC 8.10 fixes
- Misc fixes and cleanups


Alex Deucher (7):
  drm/amdgpu: switch sdma buffer function tear down to a helper
  drm/amdgpu: fix SDMA suspend/resume on SR-IOV
  drm/amd/display: make dcn32_split_stream_for_mpc_or_odm static
  drm/amd/display: fix indentation in dc.c
  drm/amd/display: make virtual_disable_link_output static
  drm/amd/display: add a license to cursor_reg_cache.h
  drm/amd/display: fix transfer function passed to build_coefficients()

Alexey Kodanev (2):
  drm/amd/pm: vega10_hwmgr: fix potential off-by-one overflow in 
'performance_levels'
  drm/amd/pm: smu7_hwmgr: fix potential off-by-one overflow in 
'performance_levels'

Alvin Lee (5):
  drm/amd/display: Only commit SubVP state after pipe programming
  drm/amd/display: Block SubVP if rotation being used
  drm/amd/display: Disable GSL when enabling phantom pipe
  drm/amd/display: For SubVP pipe split case use min transition into MPO
  drm/amd/display: Fix watermark calculation

Aric Cyr (4):
  Revert "drm/amd/display: correct hostvm flag"
  drm/amd/display: Fix vupdate and vline position calculation
  drm/amd/display: 3.2.206
  drm/amd/display: 3.2.207

Arunpravin Paneer Selvam (1):
  drm/amdgpu: Fix VRAM BO swap issue

Aurabindo Pillai (2):
  drm/amd/display: Do not trigger timing sync for phantom pipes
  drm/amd/display: Add HUBP surface flip interrupt handler

Bokun Zhang (1):
  drm/amdgpu: Fix SDMA engine resume issue under SRIOV

Candice Li (2):
  drm/amdgpu: Update umc v8_10_0 headers
  drm/amdgpu: Add poison mode query for umc v8_10_0

Charlene Liu (1):
  drm/amd/display: prevent S4 test from failing

Daniel Gomez (1):
  drm/amd/display: Fix mutex lock in dcn10

Dillon Varone (8):
  drm/amd/display: Program SubVP in dc_commit_state_no_check
  drm/amd/display: Reorder FCLK P-state switch sequence for DCN32
  drm/amd/display: Increase compbuf size prior to updating clocks
  drm/amd/display: Fix merging dynamic ODM+MPO configs on DCN32
  Revert "drm/amd/display: skip commit minimal transition state"
  drm/amd/display: Use correct pixel clock to program DTBCLK DTO's
  drm/amd/display: Acquire FCLK DPM levels on DCN32
  drm/amd/display: Fix bug preventing FCLK Pstate allow message being sent

Dmytro Laktyushkin (3):
  drm/amd/display: fix dcn315 dml detile overestimation
  drm/amd/display: add dummy pstate workaround to dcn315
  drm/amd/display: always allow pstate change when no dpps are active on 
dcn315

Dong Chenchen (1):
  drm/amd/display: Removed unused variable 'sdp_stream_enable'

Eric Bernstein (1):
  drm/amd/display: Fix disable DSC logic in the DIO code

Fangzhi Zuo (1):
  drm/amd/display: Validate DSC After Enable All New CRTCs

George Shen (1):
  drm/amd/display: Add missing SDP registers to DCN32 reglist

Guenter Roeck (1):
  drm/amd/display: fix array-bounds error in dc_stream_remove_writeback() 
[take 2]

Hamza Mahfooz (1):
  Revert "drm/amdgpu: use dirty framebuffer helper"

Ian Chen (1):
  drm/amd/display: Refactor edp ILR caps codes

Iswara Nagulendran (1):
  drm/amd/display: Allow PSR exit when panel is disconnected

Josip Pavic (1):
  drm/amd/display: do not compare integers of different widths

Jun Lei (1):
  drm/amd/display: Add a helper to map ODM/MPC/Multi-Plane resources

Leo (Hanghong) Ma (1):
  drm/amd/display: AUX tracing cleanup

Leo Chen (1):
  drm/amd/display: Add log for LTTPR

Lewis Huang (1):
  drm/amd/display: Keep OTG on when Z10 is disable

Li Zhong (1):
  drivers/amd/pm: check the return value of amdgpu_bo_kmap

Martin Leung (3):
  drm/amd/display: block odd h_total timings from halving pixel rate
  drm/amd/display: unblock mcm_luts
  drm/amd/display: zeromem mypipe heap struct before using it

Max Tseng (1):
  drm/amd/display: Use the same cursor info across features

Meenakshikumar Somasundaram (1):
  drm/amd/display: 

Re: [PATCH v2 09/14] drm/i915/gt: Always use MCR functions on multicast registers

2022-10-12 Thread Balasubramani Vivekanandan
On 30.09.2022 17:45, Matt Roper wrote:
> Rather than relying on the implicit behavior of intel_uncore_*()
> functions, let's always use the intel_gt_mcr_*() functions to operate on
> multicast/replicated registers.
> 
> v2:
>  - Add TLB invalidation registers
> 
> Signed-off-by: Matt Roper 
> ---
>  drivers/gpu/drm/i915/gt/intel_gt.c| 42 ---
>  drivers/gpu/drm/i915/gt/intel_mocs.c  | 13 +++
>  drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 12 ---
>  drivers/gpu/drm/i915/intel_pm.c   | 20 ++-
>  4 files changed, 56 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c 
> b/drivers/gpu/drm/i915/gt/intel_gt.c
> index e14f159ad9fc..e763dc719d3a 100644
> --- a/drivers/gpu/drm/i915/gt/intel_gt.c
> +++ b/drivers/gpu/drm/i915/gt/intel_gt.c
> @@ -1017,6 +1017,32 @@ get_reg_and_bit(const struct intel_engine_cs *engine, 
> const bool gen8,
>   return rb;
>  }
>  
> +/*
> + * HW architecture suggest typical invalidation time at 40us,
> + * with pessimistic cases up to 100us and a recommendation to
> + * cap at 1ms. We go a bit higher just in case.
> + */
> +#define TLB_INVAL_TIMEOUT_US 100
> +#define TLB_INVAL_TIMEOUT_MS 4
> +
> +/*
> + * On Xe_HP the TLB invalidation registers are located at the same MMIO 
> offsets
> + * but are now considered MCR registers.  Since they exist within a GAM 
> range,
> + * the primary instance of the register rolls up the status from each unit.
> + */
> +static int wait_for_invalidate(struct intel_gt *gt, struct reg_and_bit rb)
> +{
> + if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50))
> + return intel_gt_mcr_wait_for_reg_fw(gt, rb.reg, rb.bit, 0,
> + TLB_INVAL_TIMEOUT_US,
> + TLB_INVAL_TIMEOUT_MS);
> + else
> + return __intel_wait_for_register_fw(gt->uncore, rb.reg, rb.bit, 
> 0,
> + TLB_INVAL_TIMEOUT_US,
> + TLB_INVAL_TIMEOUT_MS,
> + NULL);
> +}
> +
>  static void mmio_invalidate_full(struct intel_gt *gt)
>  {

mmio_invalidate_full() contains a non-MCR register write function - 
`intel_uncore_write_fw(uncore, rb.reg, rb.bit)`
This function is used for MCR registers as well.

I notice in the later patches of the series mmio_invalidate_full() is
modified to use the MCR functions for MCR registers. But I think those
changes should be part of this patch.


Regards,
Bala

>   static const i915_reg_t gen8_regs[] = {
> @@ -1099,22 +1125,12 @@ static void mmio_invalidate_full(struct intel_gt *gt)
>   for_each_engine_masked(engine, gt, awake, tmp) {
>   struct reg_and_bit rb;
>  
> - /*
> -  * HW architecture suggest typical invalidation time at 40us,
> -  * with pessimistic cases up to 100us and a recommendation to
> -  * cap at 1ms. We go a bit higher just in case.
> -  */
> - const unsigned int timeout_us = 100;
> - const unsigned int timeout_ms = 4;
> -
>   rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num);
> - if (__intel_wait_for_register_fw(uncore,
> -  rb.reg, rb.bit, 0,
> -  timeout_us, timeout_ms,
> -  NULL))
> +
> + if (wait_for_invalidate(gt, rb))
>   drm_err_ratelimited(>i915->drm,
>   "%s TLB invalidation did not 
> complete in %ums!\n",
> - engine->name, timeout_ms);
> + engine->name, TLB_INVAL_TIMEOUT_MS);
>   }
>  
>   /*
> diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c 
> b/drivers/gpu/drm/i915/gt/intel_mocs.c
> index 06643701bf24..89ef1e06bf1d 100644
> --- a/drivers/gpu/drm/i915/gt/intel_mocs.c
> +++ b/drivers/gpu/drm/i915/gt/intel_mocs.c
> @@ -7,6 +7,7 @@
>  
>  #include "intel_engine.h"
>  #include "intel_gt.h"
> +#include "intel_gt_mcr.h"
>  #include "intel_gt_regs.h"
>  #include "intel_mocs.h"
>  #include "intel_ring.h"
> @@ -601,17 +602,17 @@ static u32 l3cc_combine(u16 low, u16 high)
>0; \
>i++)
>  
> -static void init_l3cc_table(struct intel_uncore *uncore,
> +static void init_l3cc_table(struct intel_gt *gt,
>   const struct drm_i915_mocs_table *table)
>  {
>   unsigned int i;
>   u32 l3cc;
>  
>   for_each_l3cc(l3cc, table, i)
> - if (GRAPHICS_VER_FULL(uncore->i915) >= IP_VER(12, 50))
> - intel_uncore_write_fw(uncore, XEHP_LNCFCMOCS(i), l3cc);
> + if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50))
> + intel_gt_mcr_multicast_write_fw(gt, XEHP_LNCFCMOCS(i), 
> l3cc);

Re: [PATCH v4 5/5] drm/ofdrm: Support big-endian scanout buffers

2022-10-12 Thread Michal Suchánek
On Wed, Oct 12, 2022 at 05:59:45PM +0300, Ville Syrjälä wrote:
> On Wed, Oct 12, 2022 at 04:31:14PM +0200, Thomas Zimmermann wrote:
> > Hi
> > 
> > Am 12.10.22 um 15:12 schrieb Arnd Bergmann:
> > > On Wed, Oct 12, 2022, at 2:00 PM, Thomas Zimmermann wrote:
> > >>
> > >> Could well be. But ofdrm intents to replace offb and this test has
> > >> worked well in offb for almost 15 yrs. If there are bug reports, I'm
> > >> happy to take patches, but until then I see no reason to change it.
> > > 
> > > I wouldn't change the code in offb unless a user reports a bug,
> > > but I don't see a point in adding the same mistake to ofdrm if we
> > > know it can't work on real hardware.
> > 
> > As I said, this has worked with offb and apparently on real hardware. 
> > For all I know, ATI hardware (before it became AMD) was used in PPC 
> > Macintoshs and assumed big-endian access on those machines.
> 
> At least mach64 class hardware has two frame buffer apertures, and
> byte swapping can be configured separately for each. But that means
> you only get correct byte swapping for at most two bpps at the same
> time (and that only if you know which aperture to access each time).
> IIRC Rage 128 already has the surface register stuff where you
> could byte swap a limited set of ranges independently. And old
> mga hardware has just one byte swap setting for the whole frame
> buffer aperture, so only one bpp at a time.
> 
> That kind of horrible limitations of the byte swappers is the
> main reason why I wanted to make drm fourcc endianness explicit.
> Simply assuming host endianness would end in tears on big endian
> as soon as you need to access stuff with two bpps at the same time.
> Much better to just switch off those useless byte swappers and
> swap by hand when necessary.

If you have hardware-specific driver, sure.

This is firmware-provided framebuffer, though. You get one framebuffer
address, and one endian - whatever the firmware set up and described in
the DT.

Thanks

Michal


Re: [PATCH v3 12/17] drm/i915/vm_bind: Implement I915_GEM_EXECBUFFER3 ioctl

2022-10-12 Thread Niranjana Vishwanathapura

On Wed, Oct 12, 2022 at 11:32:18AM +0100, Matthew Auld wrote:

On 10/10/2022 07:58, Niranjana Vishwanathapura wrote:

Implement new execbuf3 ioctl (I915_GEM_EXECBUFFER3) which only
works in vm_bind mode. The vm_bind mode only works with
this new execbuf3 ioctl.

The new execbuf3 ioctl will not have any list of objects to validate
bind as all required objects binding would have been requested by the
userspace before submitting the execbuf3.

Legacy features like relocations etc are not supported by execbuf3.

v2: Add more input validity checks.
v3: batch_address is a VA (not an array) if num_batches=1,
minor cleanup

Signed-off-by: Niranjana Vishwanathapura 
Signed-off-by: Andi Shyti 
---
 drivers/gpu/drm/i915/Makefile |   1 +
 .../gpu/drm/i915/gem/i915_gem_execbuffer3.c   | 580 ++
 drivers/gpu/drm/i915/gem/i915_gem_ioctls.h|   2 +
 drivers/gpu/drm/i915/i915_driver.c|   1 +
 include/uapi/drm/i915_drm.h   |  61 ++
 5 files changed, 645 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/gem/i915_gem_execbuffer3.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 3564307699ea..94520b79e7e7 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -150,6 +150,7 @@ gem-y += \
gem/i915_gem_domain.o \
gem/i915_gem_execbuffer_common.o \
gem/i915_gem_execbuffer.o \
+   gem/i915_gem_execbuffer3.o \
gem/i915_gem_internal.o \
gem/i915_gem_object.o \
gem/i915_gem_lmem.o \
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer3.c 
b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer3.c
new file mode 100644
index ..1f38f658066a
--- /dev/null
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer3.c
@@ -0,0 +1,580 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#include 
+#include 
+
+#include 
+
+#include "gt/intel_context.h"
+#include "gt/intel_gpu_commands.h"
+#include "gt/intel_gt.h"
+
+#include "i915_drv.h"
+#include "i915_gem_context.h"
+#include "i915_gem_execbuffer_common.h"
+#include "i915_gem_ioctls.h"
+#include "i915_gem_vm_bind.h"
+#include "i915_trace.h"
+
+#define __EXEC3_ENGINE_PINNED  BIT_ULL(32)
+#define __EXEC3_INTERNAL_FLAGS (~0ull << 32)
+
+/* Catch emission of unexpected errors for CI! */
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
+#undef EINVAL
+#define EINVAL ({ \
+   DRM_DEBUG_DRIVER("EINVAL at %s:%d\n", __func__, __LINE__); \
+   22; \
+})
+#endif
+
+/**
+ * DOC: User command execution with execbuf3 ioctl
+ *
+ * A VM in VM_BIND mode will not support older execbuf mode of binding.
+ * The execbuf ioctl handling in VM_BIND mode differs significantly from the
+ * older execbuf2 ioctl (See struct drm_i915_gem_execbuffer2).
+ * Hence, a new execbuf3 ioctl has been added to support VM_BIND mode. (See
+ * struct drm_i915_gem_execbuffer3). The execbuf3 ioctl will not accept any
+ * execlist. Hence, no support for implicit sync.
+ *
+ * The new execbuf3 ioctl only works in VM_BIND mode and the VM_BIND mode only
+ * works with execbuf3 ioctl for submission.
+ *
+ * The execbuf3 ioctl directly specifies the batch addresses instead of as
+ * object handles as in execbuf2 ioctl. The execbuf3 ioctl will also not
+ * support many of the older features like in/out/submit fences, fence array,
+ * default gem context etc. (See struct drm_i915_gem_execbuffer3).
+ *
+ * In VM_BIND mode, VA allocation is completely managed by the user instead of
+ * the i915 driver. Hence all VA assignment, eviction are not applicable in
+ * VM_BIND mode. Also, for determining object activeness, VM_BIND mode will not
+ * be using the i915_vma active reference tracking. It will instead check the
+ * dma-resv object's fence list for that.
+ *
+ * So, a lot of code supporting execbuf2 ioctl, like relocations, VA evictions,
+ * vma lookup table, implicit sync, vma active reference tracking etc., are not
+ * applicable for execbuf3 ioctl.


I guess EXEC_CAPTURE is also now gone? Is that expected? We ofc don't 
have the list of objects so perhaps doesn't make sense any more. Just 
double checking...


Yah, instead will have a VM_BIND_CAPTURE flag for user to request for capture
during vm_bind call. It is not implemented yet.

Niranjana



Re: [RESEND PATCH v2] drm/mediatek: Add AFBC support to Mediatek DRM driver

2022-10-12 Thread AngeloGioacchino Del Regno

Il 12/10/22 16:12, Justin Green ha scritto:

These would be different from the macros that are available in bitfield.h, but
not *fundamentally* different, so these would look a little redundant...

I think that you refer to that `pitch` variable that's coming from the DRM(/fb)
API... and bitfield macros are for register access... so I guess that one clean
way of avoiding the magic shifting (that is purely used to split the 32-bits
number in two 16-bits 'chunks') would be to perhaps use a union, so that you
will have something like u.pitch_lsb, u.pitch_msb (with lsb/msb being two u16).


Do you mean something like this?

union pitch_val {
  struct split_pitch_val {
   uint16_t lsb;
   uint16_t msb;
  } split;
  uint32_t val;
};

I think my concern with that approach would be it assumes the compiler
packs structs tightly and it also assumes the endianness of the
machine, whereas a bitshift is maybe more portable. Is this an issue
worth considering since we know this driver will only run on specific
MTK SoCs?


Yes I mean something like that (except, use u16, u32 short form)... and that
should be safe really. As for the endianness, a lot more would break already,
so I don't see that as a concern right now.


Re: [PATCH drm-misc-next v3 4/7] drm/arm/hdlcd: use drm_dev_unplug()

2022-10-12 Thread Liviu Dudau
Hi Danilo,

Appologies again for the delay in reviewing this as I was at XDC last week.

This patch is causing a regression at 'rmmod' time as the drm_crtc_vblank_off() 
does
not get called when we disable outputs and the HDLCD remains active as I keep 
getting
unhandled context faults from the arm-smmu driver that sits in front of the 
HDLCD.

This is the stack trace for it:

root@alarm ~]# rmmod hdlcd
[  198.981343] Console: switching to colour dummy device 80x25
[  199.012492] [ cut here ]
[  199.017209] driver forgot to call drm_crtc_vblank_off()
[  199.023513] WARNING: CPU: 5 PID: 176 at 
drivers/gpu/drm/drm_atomic_helper.c:1236 disable_outputs+0x2c4/0x2d0 
[drm_kms_helper]
[  199.035055] Modules linked in: hdlcd(-) drm_dma_helper tda998x cec 
drm_kms_helper drm
[  199.042929] CPU: 5 PID: 176 Comm: kworker/5:2 Not tainted 
6.0.0-rc2-7-ge17e6f0211cd #6
[  199.051212] Hardware name: ARM Juno development board (r2) (DT)
[  199.057143] Workqueue: events drm_mode_rmfb_work_fn [drm]
[  199.062831] pstate: 6005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[  199.069809] pc : disable_outputs+0x2c4/0x2d0 [drm_kms_helper]
[  199.075664] lr : disable_outputs+0x2c4/0x2d0 [drm_kms_helper]
[  199.081519] sp : 8a8f3b60
[  199.084836] x29: 8a8f3b60 x28: 0028 x27: 0008013962b8
[  199.091996] x26: 81049688 x25: 81080520 x24: 0038
[  199.099155] x23:  x22: 000801396000 x21: 0008013966f0
[  199.106314] x20:  x19: 00080a65a800 x18: 
[  199.113472] x17:  x16:  x15: 
[  199.120630] x14: 00e1 x13:  x12: 
[  199.127788] x11: 0001 x10: 0a60 x9 : 8a8f3910
[  199.134947] x8 : 00080149d480 x7 : 00097efb5bc0 x6 : 0083
[  199.142106] x5 :  x4 : 00097efaea18 x3 : 00097efb1c20
[  199.149264] x2 :  x1 :  x0 : 00080149c9c0
[  199.156423] Call trace:
[  199.158870]  disable_outputs+0x2c4/0x2d0 [drm_kms_helper]
[  199.164380]  drm_atomic_helper_commit_tail+0x24/0xa0 [drm_kms_helper]
[  199.170933]  commit_tail+0x150/0x180 [drm_kms_helper]
[  199.176093]  drm_atomic_helper_commit+0x13c/0x370 [drm_kms_helper]
[  199.182384]  drm_atomic_commit+0xa4/0xe0 [drm]
[  199.187074]  drm_framebuffer_remove+0x434/0x4d4 [drm]
[  199.192374]  drm_mode_rmfb_work_fn+0x74/0x9c [drm]
[  199.197413]  process_one_work+0x1d4/0x330
[  199.201437]  worker_thread+0x220/0x430
[  199.205195]  kthread+0x108/0x10c
[  199.208430]  ret_from_fork+0x10/0x20
[  199.212015] ---[ end trace  ]---
[  199.221088] arm-smmu 7fb1.iommu: Unhandled context fault: fsr=0x2, 
iova=0xffa53600, fsynr=0x182, cbfrsynra=0x0, cb=0
[  199.232958] arm-smmu 7fb1.iommu: Unhandled context fault: fsr=0x2, 
iova=0xff80, fsynr=0x182, cbfrsynra=0x0, cb=0
[  199.233228] [ cut here ]
[  199.248618] hdlcd 7ff5.hdlcd: drm_WARN_ON(({ do { 
__attribute__((__noreturn__)) extern void __compiletime_assert_384(void) 
__attribute__((__error__("Unsupported access size for {READ,WRITE}_ONCE()."))); 
if (!((sizeof(vblank->enabled) == sizeof(char) || sizeof(vblank->enabled) == 
sizeof(short) || sizeof(vblank->
enabled) == sizeof(int) || sizeof(vblank->enabled) == sizeof(long)) || 
sizeof(vblank->enabled) == sizeof(long long))) __compiletime_assert_384(); } 
while (0); (*(const volatile typeof( _Generic((vblank->enabled), char: (char)0, 
unsigned char: (unsigned char)0, signed char: (signed char)0, unsigned short: 
(unsigned sho
rt)0, signed short: (signed short)0, unsigned int: (unsigned int)0, signed int: 
(signed int)0, unsigned long: (unsigned long)0, signed long: (signed long)0, 
unsigned long long: (unsigned long long)0, signed long long: (signed long 
long)0, default: (vblank->enabled))) *)&(vblank->enabled)); }) && 
drm_core_check_feature
(dev, DRIVER_MODESET))
[  199.248790] WARNING: CPU: 4 PID: 285 at drivers/gpu/drm/drm_vblank.c:504 
drm_vblank_init_release+0x84/0xb0 [drm]
[  199.249751] arm-smmu 7fb1.iommu: Unhandled context fault: fsr=0x2, 
iova=0xff80, fsynr=0x182, cbfrsynra=0x0, cb=0
[  199.291902] arm-scmi firmware:scmi: timed out in resp(caller: 
scmi_perf_level_set+0xfc/0x120)
[  199.291926] cpufreq: __target_index: Failed to change cpu frequency: -110
[  199.334654] Modules linked in: hdlcd(-)
[  199.345063] scmi-cpufreq scmi_dev.2: Message for 857 type 0 is not expected!
[  199.355734]  drm_dma_helper
[  199.371060]  tda998x
[  199.384738]  cec
[  199.408686]  drm_kms_helper
[  199.421404]  drm
[  199.436732]
[  199.450409] CPU: 4 PID: 285 Comm: rmmod Tainted: GW 
6.0.0-rc2-7-ge17e6f0211cd #6
[  199.475499] Hardware name: ARM Juno development board (r2) (DT)
[  199.501541] pstate: 6005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[  199.508531] pc : 

Re: [PATCH v4 5/5] drm/ofdrm: Support big-endian scanout buffers

2022-10-12 Thread Ville Syrjälä
On Wed, Oct 12, 2022 at 04:31:14PM +0200, Thomas Zimmermann wrote:
> Hi
> 
> Am 12.10.22 um 15:12 schrieb Arnd Bergmann:
> > On Wed, Oct 12, 2022, at 2:00 PM, Thomas Zimmermann wrote:
> >>
> >> Could well be. But ofdrm intents to replace offb and this test has
> >> worked well in offb for almost 15 yrs. If there are bug reports, I'm
> >> happy to take patches, but until then I see no reason to change it.
> > 
> > I wouldn't change the code in offb unless a user reports a bug,
> > but I don't see a point in adding the same mistake to ofdrm if we
> > know it can't work on real hardware.
> 
> As I said, this has worked with offb and apparently on real hardware. 
> For all I know, ATI hardware (before it became AMD) was used in PPC 
> Macintoshs and assumed big-endian access on those machines.

At least mach64 class hardware has two frame buffer apertures, and
byte swapping can be configured separately for each. But that means
you only get correct byte swapping for at most two bpps at the same
time (and that only if you know which aperture to access each time).
IIRC Rage 128 already has the surface register stuff where you
could byte swap a limited set of ranges independently. And old
mga hardware has just one byte swap setting for the whole frame
buffer aperture, so only one bpp at a time.

That kind of horrible limitations of the byte swappers is the
main reason why I wanted to make drm fourcc endianness explicit.
Simply assuming host endianness would end in tears on big endian
as soon as you need to access stuff with two bpps at the same time.
Much better to just switch off those useless byte swappers and
swap by hand when necessary.

-- 
Ville Syrjälä
Intel


Re: [PATCH v4 5/5] drm/ofdrm: Support big-endian scanout buffers

2022-10-12 Thread Thomas Zimmermann

Hi

Am 12.10.22 um 15:12 schrieb Arnd Bergmann:

On Wed, Oct 12, 2022, at 2:00 PM, Thomas Zimmermann wrote:


Could well be. But ofdrm intents to replace offb and this test has
worked well in offb for almost 15 yrs. If there are bug reports, I'm
happy to take patches, but until then I see no reason to change it.


I wouldn't change the code in offb unless a user reports a bug,
but I don't see a point in adding the same mistake to ofdrm if we
know it can't work on real hardware.


As I said, this has worked with offb and apparently on real hardware. 
For all I know, ATI hardware (before it became AMD) was used in PPC 
Macintoshs and assumed big-endian access on those machines.



I tried to find out where this is configured in qemu, but it seems
to depend on the framebuffer backend there: most are always little-endian,
ati/bochs/vga-pci/virtio-vga are configurable from the guest through
some register setting, but vga.c picks a default from the
'TARGET_WORDS_BIGENDIAN' macro, which I think is set differently
between qemu-system-ppc64le and qemu-system-ppc64.

If you are using the framebuffer code from vga.c, I would guess that
that you can run a big-endian kernel with qemu-system-ppc64,
or a little-endian kernel with qemu-system-ppc64le and get the
correct colors, while running a little-endian kernel with
qemu-system-ppc64 and vga.c, or using a different framebuffer
emulation on a big-endian kernel would give you the wrong colors.


If qemu doesn't give us the necessary DT property, it's a qemu bug. In 
in the absence of the property, picking the kernel's endianess is a 
sensible choice.


Best regards
Thomas



Which combinations did you actually test?

  Arnd


--
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 v4 5/5] drm/ofdrm: Support big-endian scanout buffers

2022-10-12 Thread Michal Suchánek
Hello,

On Wed, Oct 12, 2022 at 03:12:35PM +0200, Arnd Bergmann wrote:
> On Wed, Oct 12, 2022, at 2:00 PM, Thomas Zimmermann wrote:
> >
> > Could well be. But ofdrm intents to replace offb and this test has 
> > worked well in offb for almost 15 yrs. If there are bug reports, I'm 
> > happy to take patches, but until then I see no reason to change it.
> 
> I wouldn't change the code in offb unless a user reports a bug,
> but I don't see a point in adding the same mistake to ofdrm if we
> know it can't work on real hardware.
> 
> I tried to find out where this is configured in qemu, but it seems
> to depend on the framebuffer backend there: most are always little-endian,
> ati/bochs/vga-pci/virtio-vga are configurable from the guest through
> some register setting, but vga.c picks a default from the
> 'TARGET_WORDS_BIGENDIAN' macro, which I think is set differently
> between qemu-system-ppc64le and qemu-system-ppc64.
> 
> If you are using the framebuffer code from vga.c, I would guess that
> that you can run a big-endian kernel with qemu-system-ppc64,
> or a little-endian kernel with qemu-system-ppc64le and get the
> correct colors, while running a little-endian kernel with
> qemu-system-ppc64 and vga.c, or using a different framebuffer
> emulation on a big-endian kernel would give you the wrong colors.

Thanks for digging this up.

That makes one thing clear: qemu does not emulate this framebuffer
property correctly, and cannot be relied on for verification.

If you can provide test results from real hardware that show the current
logic as flawed it should be changed.

In absence of such test results I think the most reasonable thing is to
keep the logic that nobody complained about for 10+ years.

Thanks

Michal


Re: [RESEND PATCH v2] drm/mediatek: Add AFBC support to Mediatek DRM driver

2022-10-12 Thread Justin Green
> These would be different from the macros that are available in bitfield.h, but
> not *fundamentally* different, so these would look a little redundant...
>
> I think that you refer to that `pitch` variable that's coming from the 
> DRM(/fb)
> API... and bitfield macros are for register access... so I guess that one 
> clean
> way of avoiding the magic shifting (that is purely used to split the 32-bits
> number in two 16-bits 'chunks') would be to perhaps use a union, so that you
> will have something like u.pitch_lsb, u.pitch_msb (with lsb/msb being two 
> u16).

Do you mean something like this?

union pitch_val {
 struct split_pitch_val {
  uint16_t lsb;
  uint16_t msb;
 } split;
 uint32_t val;
};

I think my concern with that approach would be it assumes the compiler
packs structs tightly and it also assumes the endianness of the
machine, whereas a bitshift is maybe more portable. Is this an issue
worth considering since we know this driver will only run on specific
MTK SoCs?


Re: [PATCH v2] drm: split build lists one per line and sort

2022-10-12 Thread Jani Nikula
On Wed, 12 Oct 2022, Maxime Ripard  wrote:
> On Wed, Oct 12, 2022 at 03:32:32PM +0300, Jani Nikula wrote:
>> On Tue, 11 Oct 2022, Jani Nikula  wrote:
>> > While it takes more vertical space, sorted build lists with one object
>> > per line are arguably easier to manage, especially when there are
>> > conflicting changes.
>> >
>> > Split anything with more than one object file.
>> >
>> > v2: also split drm_cache.o and put it after drm_bridge.o (Andi)
>> >
>> > Signed-off-by: Jani Nikula 
>> > Reviewed-by: Andi Shyti 
>> 
>> Cc: drm-misc maintainers, don't really want to push this without an
>> approval from you guys.
>
> Acked-by: Maxime Ripard 
>
> Thanks for doing this

Thanks, pushed to drm-misc-next.

BR,
Jani.

-- 
Jani Nikula, Intel Open Source Graphics Center


Re: [PATCH -next] drm/amdgpu/si_dma: remove unused variable in si_dma_stop()

2022-10-12 Thread Alex Deucher
Applied.  Thanks!

Alex

On Wed, Oct 12, 2022 at 3:37 AM Yang Yingliang  wrote:
>
> After commit 571c05365892 ("drm/amdgpu: switch sdma buffer function
> tear down to a helper"), the variable 'ring' is not used anymore, it
> can be removed.
>
> Signed-off-by: Yang Yingliang 
> ---
>  drivers/gpu/drm/amd/amdgpu/si_dma.c | 2 --
>  1 file changed, 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c 
> b/drivers/gpu/drm/amd/amdgpu/si_dma.c
> index 4d5e718540aa..abca8b529721 100644
> --- a/drivers/gpu/drm/amd/amdgpu/si_dma.c
> +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c
> @@ -112,14 +112,12 @@ static void si_dma_ring_emit_fence(struct amdgpu_ring 
> *ring, u64 addr, u64 seq,
>
>  static void si_dma_stop(struct amdgpu_device *adev)
>  {
> -   struct amdgpu_ring *ring;
> u32 rb_cntl;
> unsigned i;
>
> amdgpu_sdma_unset_buffer_funcs_helper(adev);
>
> for (i = 0; i < adev->sdma.num_instances; i++) {
> -   ring = >sdma.instance[i].ring;
> /* dma0 */
> rb_cntl = RREG32(DMA_RB_CNTL + sdma_offsets[i]);
> rb_cntl &= ~DMA_RB_ENABLE;
> --
> 2.25.1
>


Re: [PATCH v2] drm/sched: Fix kernel NULL pointer dereference error

2022-10-12 Thread Christian König
That essentially looks like the right approach, but I would go a few 
steps further.


I think we should add a drm_sched_fence_set_parent() function to 
sched_fence.c and move a good part of the handling into that C file. 
Just a simple signal function which tells the scheduler that it should 
decrement it's counter and wake up the main thread.


Regards,
Christian.

Am 12.10.22 um 15:22 schrieb Arvind Yadav:

This is purely a timing issue. Here, sometimes Job free
is happening before the job is done.
To fix this issue moving 'dma_fence_cb' callback from
job(struct drm_sched_job) to scheduler fence (struct drm_sched_fence).

BUG: kernel NULL pointer dereference, address: 0088
  #PF: supervisor read access in kernel mode
  #PF: error_code(0x) - not-present page
  PGD 0 P4D 0
  Oops:  [#1] PREEMPT SMP NOPTI
  CPU: 2 PID: 0 Comm: swapper/2 Not tainted 6.0.0-rc2-custom #1
  Arvind : [dma_fence_default_wait _START] timeout = -1
  Hardware name: AMD Dibbler/Dibbler, BIOS RDB1107CC 09/26/2018
  RIP: 0010:drm_sched_job_done.isra.0+0x11/0x140 [gpu_sched]
  Code: 8b fe ff ff be 03 00 00 00 e8 7b da b7 e3 e9 d4 fe ff ff 66 0f 1f 44 00 00 0f 
1f 44 00 00 55 48 89 e5 41 55 41 54 49 89 fc 53 <48> 8b 9f 88 00 00 00 f0 ff 8b 
f0 00 00 00 48 8b 83 80 01 00 00 f0
  RSP: 0018:b1b1801d4d38 EFLAGS: 00010087
  RAX: c0aa48b0 RBX: b1b1801d4d70 RCX: 0018
  RDX: 36c70afb7c1d RSI: 8a45ca413c60 RDI: 
  RBP: b1b1801d4d50 R08: 00b5 R09: 
  R10:  R11:  R12: 
  R13: b1b1801d4d70 R14: 8a45c416 R15: 8a45c416a708
  FS:  () GS:8a48a0a8() knlGS:
  CS:  0010 DS:  ES:  CR0: 80050033
  CR2: 0088 CR3: 00014ad5 CR4: 003506e0
  Call Trace:
   
   drm_sched_job_done_cb+0x12/0x20 [gpu_sched]
   dma_fence_signal_timestamp_locked+0x7e/0x110
   dma_fence_signal+0x31/0x60
   amdgpu_fence_process+0xc4/0x140 [amdgpu]
   gfx_v9_0_eop_irq+0x9d/0xd0 [amdgpu]
   amdgpu_irq_dispatch+0xb7/0x210 [amdgpu]
   amdgpu_ih_process+0x86/0x100 [amdgpu]
   amdgpu_irq_handler+0x24/0x60 [amdgpu]
   __handle_irq_event_percpu+0x4b/0x190
   handle_irq_event_percpu+0x15/0x50
   handle_irq_event+0x39/0x60
   handle_edge_irq+0xaf/0x210
   __common_interrupt+0x6e/0x110
   common_interrupt+0xc1/0xe0
   
   

Signed-off-by: Arvind Yadav 
---

Changes in v2: Moving 'dma_fence_cb' callback from
job(struct drm_sched_job) to scheduler fence(struct drm_sched_fence)
instead of adding NULL check for s_fence.

---
  drivers/gpu/drm/scheduler/sched_main.c | 23 +++
  include/drm/gpu_scheduler.h|  6 --
  2 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/scheduler/sched_main.c 
b/drivers/gpu/drm/scheduler/sched_main.c
index 4cc59bae38dd..62d8eca05b92 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -253,13 +253,12 @@ drm_sched_rq_select_entity_fifo(struct drm_sched_rq *rq)
  
  /**

   * drm_sched_job_done - complete a job
- * @s_job: pointer to the job which is done
+ * @s_fence: pointer to the fence of a done job
   *
   * Finish the job's fence and wake up the worker thread.
   */
-static void drm_sched_job_done(struct drm_sched_job *s_job)
+static void drm_sched_job_done(struct drm_sched_fence *s_fence)
  {
-   struct drm_sched_fence *s_fence = s_job->s_fence;
struct drm_gpu_scheduler *sched = s_fence->sched;
  
  	atomic_dec(>hw_rq_count);

@@ -280,9 +279,9 @@ static void drm_sched_job_done(struct drm_sched_job *s_job)
   */
  static void drm_sched_job_done_cb(struct dma_fence *f, struct dma_fence_cb 
*cb)
  {
-   struct drm_sched_job *s_job = container_of(cb, struct drm_sched_job, 
cb);
+   struct drm_sched_fence *s_fence = container_of(cb, struct 
drm_sched_fence, cb);
  
-	drm_sched_job_done(s_job);

+   drm_sched_job_done(s_fence);
  }
  
  /**

@@ -506,7 +505,7 @@ void drm_sched_stop(struct drm_gpu_scheduler *sched, struct 
drm_sched_job *bad)
 list) {
if (s_job->s_fence->parent &&
dma_fence_remove_callback(s_job->s_fence->parent,
- _job->cb)) {
+ _job->s_fence->cb)) {
dma_fence_put(s_job->s_fence->parent);
s_job->s_fence->parent = NULL;
atomic_dec(>hw_rq_count);
@@ -576,15 +575,15 @@ void drm_sched_start(struct drm_gpu_scheduler *sched, 
bool full_recovery)
continue;
  
  		if (fence) {

-   r = dma_fence_add_callback(fence, _job->cb,
+   r = dma_fence_add_callback(fence, _job->s_fence->cb,
   drm_sched_job_done_cb);
if (r 

Re: [PATCH resend v2] drm/amdgpu: fix enum conversion in display_mode_vba

2022-10-12 Thread Zeng Heng
Hi, I just wonder is there any further comment towards this patch? or 
anything needs to be correct?



Greetings,

Zeng Heng


On 2022/9/22 17:18, Zeng Heng wrote:

Fix below compile warning when open enum-conversion
option check (compiled with -Wenum-conversion):

drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn20/display_mode_vba_20.c:
In function ‘dml20_ModeSupportAndSystemConfigurationFull’:
drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn20/display_mode_vba_20.c:3900:44:
error: implicit conversion from ‘enum ’ to ‘enum odm_combine_mode’ 
[-Werror=enum-conversion]
  3900 | locals->ODMCombineEnablePerState[i][k] = false;
   |^
drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn20/display_mode_vba_20.c:3904:46:
error: implicit conversion from ‘enum ’ to ‘enum odm_combine_mode’ 
[-Werror=enum-conversion]
  3904 |   locals->ODMCombineEnablePerState[i][k] = true;
   |  ^
drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn20/display_mode_vba_20.c:3907:46:
error: implicit conversion from ‘enum ’ to ‘enum odm_combine_mode’ 
[-Werror=enum-conversion]
  3907 |   locals->ODMCombineEnablePerState[i][k] = true;
   |  ^
drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn20/display_mode_vba_20.c:3960:45:
error: implicit conversion from ‘enum ’ to ‘enum odm_combine_mode’ 
[-Werror=enum-conversion]
  3960 |  locals->ODMCombineEnablePerState[i][k] = false;

Use the proper value from the right enumerated type,
dm_odm_combine_mode_disabled & dm_odm_combine_mode_2to1,
so there is no more implicit conversion.

The numerical values of dm_odm_combine_mode_disabled
& false and dm_odm_combine_mode_2to1 & true
happen to be the same, so there is no change in
behavior.

Signed-off-by: Zeng Heng 
---
  .../amd/display/dc/dml/dcn20/display_mode_vba_20.c   |  8 
  .../amd/display/dc/dml/dcn20/display_mode_vba_20v2.c | 10 +-
  .../amd/display/dc/dml/dcn21/display_mode_vba_21.c   | 12 ++--
  3 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c 
b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c
index d3b5b6fedf04..6266b0788387 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c
@@ -3897,14 +3897,14 @@ void dml20_ModeSupportAndSystemConfigurationFull(struct 
display_mode_lib *mode_l

mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine = mode_lib->vba.PixelClock[k] 
/ 2
* (1 + 
mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0);
  
-locals->ODMCombineEnablePerState[i][k] = false;

+   locals->ODMCombineEnablePerState[i][k] = 
dm_odm_combine_mode_disabled;
mode_lib->vba.PlaneRequiredDISPCLK = 
mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine;
if (mode_lib->vba.ODMCapability) {
if 
(locals->PlaneRequiredDISPCLKWithoutODMCombine > 
mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity) {
-   
locals->ODMCombineEnablePerState[i][k] = true;
+   
locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1;
mode_lib->vba.PlaneRequiredDISPCLK 
= mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine;
} else if (locals->HActive[k] > 
DCN20_MAX_420_IMAGE_WIDTH && locals->OutputFormat[k] == dm_420) {
-   
locals->ODMCombineEnablePerState[i][k] = true;
+   
locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1;
mode_lib->vba.PlaneRequiredDISPCLK 
= mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine;
}
}
@@ -3957,7 +3957,7 @@ void dml20_ModeSupportAndSystemConfigurationFull(struct 
display_mode_lib *mode_l
locals->RequiredDISPCLK[i][j] = 0.0;
locals->DISPCLK_DPPCLK_Support[i][j] = true;
for (k = 0; k <= 
mode_lib->vba.NumberOfActivePlanes - 1; k++) {
-   locals->ODMCombineEnablePerState[i][k] 
= false;
+   locals->ODMCombineEnablePerState[i][k] 
= dm_odm_combine_mode_disabled;
if (locals->SwathWidthYSingleDPP[k] <= 
locals->MaximumSwathWidth[k]) {
locals->NoOfDPP[i][j][k] = 1;

[PATCH v2] drm/sched: Fix kernel NULL pointer dereference error

2022-10-12 Thread Arvind Yadav
This is purely a timing issue. Here, sometimes Job free
is happening before the job is done.
To fix this issue moving 'dma_fence_cb' callback from
job(struct drm_sched_job) to scheduler fence (struct drm_sched_fence).

BUG: kernel NULL pointer dereference, address: 0088
 #PF: supervisor read access in kernel mode
 #PF: error_code(0x) - not-present page
 PGD 0 P4D 0
 Oops:  [#1] PREEMPT SMP NOPTI
 CPU: 2 PID: 0 Comm: swapper/2 Not tainted 6.0.0-rc2-custom #1
 Arvind : [dma_fence_default_wait _START] timeout = -1
 Hardware name: AMD Dibbler/Dibbler, BIOS RDB1107CC 09/26/2018
 RIP: 0010:drm_sched_job_done.isra.0+0x11/0x140 [gpu_sched]
 Code: 8b fe ff ff be 03 00 00 00 e8 7b da b7 e3 e9 d4 fe ff ff 66 0f 1f 44 00 
00 0f 1f 44 00 00 55 48 89 e5 41 55 41 54 49 89 fc 53 <48> 8b 9f 88 00 00 00 f0 
ff 8b f0 00 00 00 48 8b 83 80 01 00 00 f0
 RSP: 0018:b1b1801d4d38 EFLAGS: 00010087
 RAX: c0aa48b0 RBX: b1b1801d4d70 RCX: 0018
 RDX: 36c70afb7c1d RSI: 8a45ca413c60 RDI: 
 RBP: b1b1801d4d50 R08: 00b5 R09: 
 R10:  R11:  R12: 
 R13: b1b1801d4d70 R14: 8a45c416 R15: 8a45c416a708
 FS:  () GS:8a48a0a8() knlGS:
 CS:  0010 DS:  ES:  CR0: 80050033
 CR2: 0088 CR3: 00014ad5 CR4: 003506e0
 Call Trace:
  
  drm_sched_job_done_cb+0x12/0x20 [gpu_sched]
  dma_fence_signal_timestamp_locked+0x7e/0x110
  dma_fence_signal+0x31/0x60
  amdgpu_fence_process+0xc4/0x140 [amdgpu]
  gfx_v9_0_eop_irq+0x9d/0xd0 [amdgpu]
  amdgpu_irq_dispatch+0xb7/0x210 [amdgpu]
  amdgpu_ih_process+0x86/0x100 [amdgpu]
  amdgpu_irq_handler+0x24/0x60 [amdgpu]
  __handle_irq_event_percpu+0x4b/0x190
  handle_irq_event_percpu+0x15/0x50
  handle_irq_event+0x39/0x60
  handle_edge_irq+0xaf/0x210
  __common_interrupt+0x6e/0x110
  common_interrupt+0xc1/0xe0
  
  

Signed-off-by: Arvind Yadav 
---

Changes in v2: Moving 'dma_fence_cb' callback from
job(struct drm_sched_job) to scheduler fence(struct drm_sched_fence)
instead of adding NULL check for s_fence.

---
 drivers/gpu/drm/scheduler/sched_main.c | 23 +++
 include/drm/gpu_scheduler.h|  6 --
 2 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/scheduler/sched_main.c 
b/drivers/gpu/drm/scheduler/sched_main.c
index 4cc59bae38dd..62d8eca05b92 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -253,13 +253,12 @@ drm_sched_rq_select_entity_fifo(struct drm_sched_rq *rq)
 
 /**
  * drm_sched_job_done - complete a job
- * @s_job: pointer to the job which is done
+ * @s_fence: pointer to the fence of a done job
  *
  * Finish the job's fence and wake up the worker thread.
  */
-static void drm_sched_job_done(struct drm_sched_job *s_job)
+static void drm_sched_job_done(struct drm_sched_fence *s_fence)
 {
-   struct drm_sched_fence *s_fence = s_job->s_fence;
struct drm_gpu_scheduler *sched = s_fence->sched;
 
atomic_dec(>hw_rq_count);
@@ -280,9 +279,9 @@ static void drm_sched_job_done(struct drm_sched_job *s_job)
  */
 static void drm_sched_job_done_cb(struct dma_fence *f, struct dma_fence_cb *cb)
 {
-   struct drm_sched_job *s_job = container_of(cb, struct drm_sched_job, 
cb);
+   struct drm_sched_fence *s_fence = container_of(cb, struct 
drm_sched_fence, cb);
 
-   drm_sched_job_done(s_job);
+   drm_sched_job_done(s_fence);
 }
 
 /**
@@ -506,7 +505,7 @@ void drm_sched_stop(struct drm_gpu_scheduler *sched, struct 
drm_sched_job *bad)
 list) {
if (s_job->s_fence->parent &&
dma_fence_remove_callback(s_job->s_fence->parent,
- _job->cb)) {
+ _job->s_fence->cb)) {
dma_fence_put(s_job->s_fence->parent);
s_job->s_fence->parent = NULL;
atomic_dec(>hw_rq_count);
@@ -576,15 +575,15 @@ void drm_sched_start(struct drm_gpu_scheduler *sched, 
bool full_recovery)
continue;
 
if (fence) {
-   r = dma_fence_add_callback(fence, _job->cb,
+   r = dma_fence_add_callback(fence, _job->s_fence->cb,
   drm_sched_job_done_cb);
if (r == -ENOENT)
-   drm_sched_job_done(s_job);
+   drm_sched_job_done(s_job->s_fence);
else if (r)
DRM_DEV_ERROR(sched->dev, "fence add callback 
failed (%d)\n",
  r);
} else
-   drm_sched_job_done(s_job);
+   drm_sched_job_done(s_job->s_fence);
   

Re: [PATCH v2] drm/syncobj: add IOCTL to register an eventfd

2022-10-12 Thread Pekka Paalanen
On Wed, 12 Oct 2022 12:32:53 +
Simon Ser  wrote:

> Introduce a new DRM_IOCTL_SYNCOBJ_EVENTFD IOCTL which signals an
> eventfd from a syncobj.
> 
> This is useful for Wayland compositors to handle wait-before-submit.
> Wayland clients can send a timeline point to the compositor
> before the point has materialized yet, then compositors can wait
> for the point to materialize via this new IOCTL.
> 
> The existing DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT IOCTL is not suitable
> because it blocks. Compositors want to integrate the wait with
> their poll(2)-based event loop.
> 
> v2:
> - Wait for fence when flags is zero
> - Improve documentation (Pekka)
> - Rename IOCTL (Christian)
> - Fix typo in drm_syncobj_add_eventfd() (Christian)
> 
> Signed-off-by: Simon Ser 
> Cc: Jason Ekstrand 
> Cc: Daniel Vetter 
> Cc: Christian König 
> Cc: Bas Nieuwenhuizen 
> Cc: Daniel Stone 
> Cc: Pekka Paalanen 
> Cc: James Jones 
> ---
> 
> Toy user-space available at:
> https://paste.sr.ht/~emersion/674bd4fc614570f262b5bb2213be5c77d68944ac
> 
>  drivers/gpu/drm/drm_internal.h |   2 +
>  drivers/gpu/drm/drm_ioctl.c|   2 +
>  drivers/gpu/drm/drm_syncobj.c  | 143 +++--
>  include/drm/drm_syncobj.h  |   6 +-
>  include/uapi/drm/drm.h |  22 +
>  5 files changed, 168 insertions(+), 7 deletions(-)
> 

...

> diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
> index 642808520d92..5ac0a48b0169 100644
> --- a/include/uapi/drm/drm.h
> +++ b/include/uapi/drm/drm.h
> @@ -909,6 +909,27 @@ struct drm_syncobj_timeline_wait {
>   __u32 pad;
>  };
>  
> +/**
> + * struct drm_syncobj_eventfd
> + * @handle: syncobj handle.
> + * @flags: Zero to wait for the point to be signalled, or
> + * _SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE to wait for a fence to be
> + * available for the point.
> + * @point: syncobj timeline point (set to zero for binary syncobjs).
> + * @fd: Existing eventfd to sent events to.
> + * @pad: Must be zero.
> + *
> + * Register an eventfd to be signalled by a syncobj. The eventfd counter will
> + * be incremented by one.
> + */
> +struct drm_syncobj_eventfd {
> + __u32 handle;
> + __u32 flags;
> + __u64 point;
> + __s32 fd;
> + __u32 pad;
> +};
> +
>  
>  struct drm_syncobj_array {
>   __u64 handles;
> @@ -1095,6 +1116,7 @@ extern "C" {
>  #define DRM_IOCTL_SYNCOBJ_QUERY  DRM_IOWR(0xCB, struct 
> drm_syncobj_timeline_array)
>  #define DRM_IOCTL_SYNCOBJ_TRANSFER   DRM_IOWR(0xCC, struct 
> drm_syncobj_transfer)
>  #define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNALDRM_IOWR(0xCD, struct 
> drm_syncobj_timeline_array)
> +#define DRM_IOCTL_SYNCOBJ_EVENTFDDRM_IOWR(0xCE, struct 
> drm_syncobj_eventfd)
>  
>  /**
>   * DRM_IOCTL_MODE_GETFB2 - Get framebuffer metadata.

Hi,

UAPI

Acked-by: Pekka Paalanen 

with the disclaimer that I know nothing about syncobjs. The doc sounds
good though, and I read through eventfd man page to see that the
increment makes sense.

I think there is also a way initialize eventfd with 0x - N
where N is the number of syncobjs you want to wait, and then poll for
readable. Once the Nth syncobj fires, the eventfd overflows and polls
readable (and produces POLLERR). Maybe that's abuse, and maybe you
usually have no need to poll for all of a set of syncobjs, so fine.

I suspect the Wayland compositor use case wants to know about each
syncobj individually, so either you have one eventfd per syncobj or
poll for "any" in an eventfd with multiple syncobjs and check them all
each time it polls readable.

Seems fine to me.


Thanks,
pq


pgp05kHCKXQ4j.pgp
Description: OpenPGP digital signature


Re: [PATCH v4 5/5] drm/ofdrm: Support big-endian scanout buffers

2022-10-12 Thread Arnd Bergmann
On Wed, Oct 12, 2022, at 2:00 PM, Thomas Zimmermann wrote:
>
> Could well be. But ofdrm intents to replace offb and this test has 
> worked well in offb for almost 15 yrs. If there are bug reports, I'm 
> happy to take patches, but until then I see no reason to change it.

I wouldn't change the code in offb unless a user reports a bug,
but I don't see a point in adding the same mistake to ofdrm if we
know it can't work on real hardware.

I tried to find out where this is configured in qemu, but it seems
to depend on the framebuffer backend there: most are always little-endian,
ati/bochs/vga-pci/virtio-vga are configurable from the guest through
some register setting, but vga.c picks a default from the
'TARGET_WORDS_BIGENDIAN' macro, which I think is set differently
between qemu-system-ppc64le and qemu-system-ppc64.

If you are using the framebuffer code from vga.c, I would guess that
that you can run a big-endian kernel with qemu-system-ppc64,
or a little-endian kernel with qemu-system-ppc64le and get the
correct colors, while running a little-endian kernel with
qemu-system-ppc64 and vga.c, or using a different framebuffer
emulation on a big-endian kernel would give you the wrong colors.

Which combinations did you actually test?

 Arnd


Re: [PATCH v2] drm: split build lists one per line and sort

2022-10-12 Thread Maxime Ripard
On Wed, Oct 12, 2022 at 03:32:32PM +0300, Jani Nikula wrote:
> On Tue, 11 Oct 2022, Jani Nikula  wrote:
> > While it takes more vertical space, sorted build lists with one object
> > per line are arguably easier to manage, especially when there are
> > conflicting changes.
> >
> > Split anything with more than one object file.
> >
> > v2: also split drm_cache.o and put it after drm_bridge.o (Andi)
> >
> > Signed-off-by: Jani Nikula 
> > Reviewed-by: Andi Shyti 
> 
> Cc: drm-misc maintainers, don't really want to push this without an
> approval from you guys.

Acked-by: Maxime Ripard 

Thanks for doing this

Maxime


signature.asc
Description: PGP signature


Re: [PATCH] drm/ttm: Remove unnecessary drm_mm_clean

2022-10-12 Thread Zeng Heng



On 2022/10/12 20:56, Christian König wrote:

Am 12.10.22 um 14:47 schrieb Zeng Heng:

Remove unnecessary `drm_mm_clean` calling in
`ttm_range_man_fini_nocheck`, due to effective
check is already included in the following
`drm_mm_takedown`.

Signed-off-by: Zeng Heng 


Reviewed-by: Christian König 

Can you push it to drm-misc-next or should I do that?


This patch applied to drm next is OK for me, if it is at your convenience.

B.R.,

Zeng Heng



Thanks,
Christian.


---
  drivers/gpu/drm/ttm/ttm_range_manager.c | 1 -
  1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c 
b/drivers/gpu/drm/ttm/ttm_range_manager.c

index 4cfef2b3514d..f7c16c46cfbc 100644
--- a/drivers/gpu/drm/ttm/ttm_range_manager.c
+++ b/drivers/gpu/drm/ttm/ttm_range_manager.c
@@ -229,7 +229,6 @@ int ttm_range_man_fini_nocheck(struct ttm_device 
*bdev,

  return ret;
    spin_lock(>lock);
-    drm_mm_clean(mm);
  drm_mm_takedown(mm);
  spin_unlock(>lock);




Re: [PATCH] drm/ttm: Remove unnecessary drm_mm_clean

2022-10-12 Thread Christian König

Am 12.10.22 um 14:47 schrieb Zeng Heng:

Remove unnecessary `drm_mm_clean` calling in
`ttm_range_man_fini_nocheck`, due to effective
check is already included in the following
`drm_mm_takedown`.

Signed-off-by: Zeng Heng 


Reviewed-by: Christian König 

Can you push it to drm-misc-next or should I do that?

Thanks,
Christian.


---
  drivers/gpu/drm/ttm/ttm_range_manager.c | 1 -
  1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c 
b/drivers/gpu/drm/ttm/ttm_range_manager.c
index 4cfef2b3514d..f7c16c46cfbc 100644
--- a/drivers/gpu/drm/ttm/ttm_range_manager.c
+++ b/drivers/gpu/drm/ttm/ttm_range_manager.c
@@ -229,7 +229,6 @@ int ttm_range_man_fini_nocheck(struct ttm_device *bdev,
return ret;
  
  	spin_lock(>lock);

-   drm_mm_clean(mm);
drm_mm_takedown(mm);
spin_unlock(>lock);
  




[PATCH] drm/ttm: Remove unnecessary drm_mm_clean

2022-10-12 Thread Zeng Heng
Remove unnecessary `drm_mm_clean` calling in
`ttm_range_man_fini_nocheck`, due to effective
check is already included in the following
`drm_mm_takedown`.

Signed-off-by: Zeng Heng 
---
 drivers/gpu/drm/ttm/ttm_range_manager.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c 
b/drivers/gpu/drm/ttm/ttm_range_manager.c
index 4cfef2b3514d..f7c16c46cfbc 100644
--- a/drivers/gpu/drm/ttm/ttm_range_manager.c
+++ b/drivers/gpu/drm/ttm/ttm_range_manager.c
@@ -229,7 +229,6 @@ int ttm_range_man_fini_nocheck(struct ttm_device *bdev,
return ret;
 
spin_lock(>lock);
-   drm_mm_clean(mm);
drm_mm_takedown(mm);
spin_unlock(>lock);
 
-- 
2.25.1



Re: [PATCH v2] drm/syncobj: add IOCTL to register an eventfd

2022-10-12 Thread Christian König

Am 12.10.22 um 14:32 schrieb Simon Ser:

Introduce a new DRM_IOCTL_SYNCOBJ_EVENTFD IOCTL which signals an
eventfd from a syncobj.

This is useful for Wayland compositors to handle wait-before-submit.
Wayland clients can send a timeline point to the compositor
before the point has materialized yet, then compositors can wait
for the point to materialize via this new IOCTL.

The existing DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT IOCTL is not suitable
because it blocks. Compositors want to integrate the wait with
their poll(2)-based event loop.

v2:
- Wait for fence when flags is zero
- Improve documentation (Pekka)
- Rename IOCTL (Christian)
- Fix typo in drm_syncobj_add_eventfd() (Christian)

Signed-off-by: Simon Ser 
Cc: Jason Ekstrand 
Cc: Daniel Vetter 
Cc: Christian König 
Cc: Bas Nieuwenhuizen 
Cc: Daniel Stone 
Cc: Pekka Paalanen 
Cc: James Jones 


Reviewed-by: Christian König 


---

Toy user-space available at:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpaste.sr.ht%2F~emersion%2F674bd4fc614570f262b5bb2213be5c77d68944acdata=05%7C01%7Cchristian.koenig%40amd.com%7C5cc939311a00477ef8eb08daac4de7ea%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C638011747896643399%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7Csdata=COiWGlyLQiqvVJlMaz2BcGLXqVGktLuJTl7CC7jpfDU%3Dreserved=0

  drivers/gpu/drm/drm_internal.h |   2 +
  drivers/gpu/drm/drm_ioctl.c|   2 +
  drivers/gpu/drm/drm_syncobj.c  | 143 +++--
  include/drm/drm_syncobj.h  |   6 +-
  include/uapi/drm/drm.h |  22 +
  5 files changed, 168 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index 1fbbc19f1ac0..ca320e155b69 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -242,6 +242,8 @@ int drm_syncobj_wait_ioctl(struct drm_device *dev, void 
*data,
   struct drm_file *file_private);
  int drm_syncobj_timeline_wait_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_private);
+int drm_syncobj_eventfd_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_private);
  int drm_syncobj_reset_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_private);
  int drm_syncobj_signal_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index ca2a6e6101dc..95ec9a02f8a7 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -702,6 +702,8 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
  DRM_RENDER_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, 
drm_syncobj_timeline_wait_ioctl,
  DRM_RENDER_ALLOW),
+   DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_EVENTFD, drm_syncobj_eventfd_ioctl,
+ DRM_RENDER_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_RESET, drm_syncobj_reset_ioctl,
  DRM_RENDER_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_SIGNAL, drm_syncobj_signal_ioctl,
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 0c2be8360525..659577ad8c07 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -185,6 +185,7 @@
  
  #include 

  #include 
+#include 
  #include 
  #include 
  #include 
@@ -212,6 +213,20 @@ struct syncobj_wait_entry {
  static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj,
  struct syncobj_wait_entry *wait);
  
+struct syncobj_eventfd_entry {

+   struct list_head node;
+   struct dma_fence *fence;
+   struct dma_fence_cb fence_cb;
+   struct drm_syncobj *syncobj;
+   struct eventfd_ctx *ev_fd_ctx;
+   u64 point;
+   u32 flags;
+};
+
+static void
+syncobj_eventfd_entry_func(struct drm_syncobj *syncobj,
+  struct syncobj_eventfd_entry *entry);
+
  /**
   * drm_syncobj_find - lookup and reference a sync object.
   * @file_private: drm file private pointer
@@ -274,6 +289,27 @@ static void drm_syncobj_remove_wait(struct drm_syncobj 
*syncobj,
spin_unlock(>lock);
  }
  
+static void

+syncobj_eventfd_entry_free(struct syncobj_eventfd_entry *entry)
+{
+   eventfd_ctx_put(entry->ev_fd_ctx);
+   dma_fence_put(entry->fence);
+   /* This happens either inside the syncobj lock, or after the node has
+* already been removed from the list */
+   list_del(>node);
+   kfree(entry);
+}
+
+static void
+drm_syncobj_add_eventfd(struct drm_syncobj *syncobj,
+   struct syncobj_eventfd_entry *entry)
+{
+   spin_lock(>lock);
+   list_add_tail(>node, >ev_fd_list);
+   syncobj_eventfd_entry_func(syncobj, entry);
+   spin_unlock(>lock);
+}
+
  /**
   * drm_syncobj_add_point - add new timeline point to the syncobj
   * 

Re: [RFC PATCH v5 6/6] drm/tidss: Enable Dual and Duplicate Modes for OLDI

2022-10-12 Thread Tomi Valkeinen

On 28/09/2022 20:52, Aradhya Bhatia wrote:

The AM625 DSS IP contains 2 OLDI TXes which can work to enable 2
duplicated displays of smaller resolutions or enable a single Dual Link
display with a higher resolution (1920x1200).

Configure the necessary register to enable and disable the OLDI TXes
with necessary modes configurations.

Signed-off-by: Aradhya Bhatia 
---
  drivers/gpu/drm/tidss/tidss_dispc.c | 28 ++--
  1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c 
b/drivers/gpu/drm/tidss/tidss_dispc.c
index 68444e0cd8d7..fd7f49535f0c 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.c
+++ b/drivers/gpu/drm/tidss/tidss_dispc.c
@@ -1003,8 +1003,8 @@ static void dispc_enable_oldi(struct dispc_device *dispc, 
u32 hw_videoport,
int count = 0;
  
  	/*

-* For the moment DUALMODESYNC, MASTERSLAVE, MODE, and SRC
-* bits of DISPC_VP_DSS_OLDI_CFG are set statically to 0.
+* For the moment MASTERSLAVE, and SRC bits of DISPC_VP_DSS_OLDI_CFG are
+* set statically to 0.
 */


While at it, maybe say "are always set to 0". At least to me that's much 
more understandable.


  
  	if (fmt->data_width == 24)

@@ -1021,6 +1021,30 @@ static void dispc_enable_oldi(struct dispc_device 
*dispc, u32 hw_videoport,
  
  	oldi_cfg |= BIT(0); /* ENABLE */
  
+	switch (dispc->oldi_mode) {

+   case OLDI_MODE_OFF:
+   oldi_cfg &= ~BIT(0); /* DISABLE */


Hmm, do we call this if OLDI_MODE_OFF? The current code always enabled 
OLDI here, so I presume we call this only when we actually want to 
enable it.



+   break;
+
+   case OLDI_SINGLE_LINK_SINGLE_MODE:
+   /* All configuration is done for this mode.  */
+   break;
+
+   case OLDI_SINGLE_LINK_CLONE_MODE:
+   oldi_cfg |= BIT(5); /* CLONE MODE */
+   break;
+
+   case OLDI_DUAL_LINK_MODE:
+   oldi_cfg |= BIT(11); /* DUALMODESYNC */
+   oldi_cfg |= BIT(3); /* data-mapping field also indicates 
dual-link mode */
+   break;
+
+   default:
+   dev_warn(dispc->dev, "%s: Incorrect oldi mode. Returning.\n",
+__func__);
+   return;
+   }
+
dispc_vp_write(dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, oldi_cfg);
  
  	while (!(oldi_reset_bit & dispc_read(dispc, DSS_SYSSTATUS)) &&




[PATCH v2] drm/syncobj: add IOCTL to register an eventfd

2022-10-12 Thread Simon Ser
Introduce a new DRM_IOCTL_SYNCOBJ_EVENTFD IOCTL which signals an
eventfd from a syncobj.

This is useful for Wayland compositors to handle wait-before-submit.
Wayland clients can send a timeline point to the compositor
before the point has materialized yet, then compositors can wait
for the point to materialize via this new IOCTL.

The existing DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT IOCTL is not suitable
because it blocks. Compositors want to integrate the wait with
their poll(2)-based event loop.

v2:
- Wait for fence when flags is zero
- Improve documentation (Pekka)
- Rename IOCTL (Christian)
- Fix typo in drm_syncobj_add_eventfd() (Christian)

Signed-off-by: Simon Ser 
Cc: Jason Ekstrand 
Cc: Daniel Vetter 
Cc: Christian König 
Cc: Bas Nieuwenhuizen 
Cc: Daniel Stone 
Cc: Pekka Paalanen 
Cc: James Jones 
---

Toy user-space available at:
https://paste.sr.ht/~emersion/674bd4fc614570f262b5bb2213be5c77d68944ac

 drivers/gpu/drm/drm_internal.h |   2 +
 drivers/gpu/drm/drm_ioctl.c|   2 +
 drivers/gpu/drm/drm_syncobj.c  | 143 +++--
 include/drm/drm_syncobj.h  |   6 +-
 include/uapi/drm/drm.h |  22 +
 5 files changed, 168 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index 1fbbc19f1ac0..ca320e155b69 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -242,6 +242,8 @@ int drm_syncobj_wait_ioctl(struct drm_device *dev, void 
*data,
   struct drm_file *file_private);
 int drm_syncobj_timeline_wait_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_private);
+int drm_syncobj_eventfd_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_private);
 int drm_syncobj_reset_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_private);
 int drm_syncobj_signal_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index ca2a6e6101dc..95ec9a02f8a7 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -702,6 +702,8 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
  DRM_RENDER_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, 
drm_syncobj_timeline_wait_ioctl,
  DRM_RENDER_ALLOW),
+   DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_EVENTFD, drm_syncobj_eventfd_ioctl,
+ DRM_RENDER_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_RESET, drm_syncobj_reset_ioctl,
  DRM_RENDER_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_SIGNAL, drm_syncobj_signal_ioctl,
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 0c2be8360525..659577ad8c07 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -185,6 +185,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -212,6 +213,20 @@ struct syncobj_wait_entry {
 static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj,
  struct syncobj_wait_entry *wait);
 
+struct syncobj_eventfd_entry {
+   struct list_head node;
+   struct dma_fence *fence;
+   struct dma_fence_cb fence_cb;
+   struct drm_syncobj *syncobj;
+   struct eventfd_ctx *ev_fd_ctx;
+   u64 point;
+   u32 flags;
+};
+
+static void
+syncobj_eventfd_entry_func(struct drm_syncobj *syncobj,
+  struct syncobj_eventfd_entry *entry);
+
 /**
  * drm_syncobj_find - lookup and reference a sync object.
  * @file_private: drm file private pointer
@@ -274,6 +289,27 @@ static void drm_syncobj_remove_wait(struct drm_syncobj 
*syncobj,
spin_unlock(>lock);
 }
 
+static void
+syncobj_eventfd_entry_free(struct syncobj_eventfd_entry *entry)
+{
+   eventfd_ctx_put(entry->ev_fd_ctx);
+   dma_fence_put(entry->fence);
+   /* This happens either inside the syncobj lock, or after the node has
+* already been removed from the list */
+   list_del(>node);
+   kfree(entry);
+}
+
+static void
+drm_syncobj_add_eventfd(struct drm_syncobj *syncobj,
+   struct syncobj_eventfd_entry *entry)
+{
+   spin_lock(>lock);
+   list_add_tail(>node, >ev_fd_list);
+   syncobj_eventfd_entry_func(syncobj, entry);
+   spin_unlock(>lock);
+}
+
 /**
  * drm_syncobj_add_point - add new timeline point to the syncobj
  * @syncobj: sync object to add timeline point do
@@ -288,7 +324,8 @@ void drm_syncobj_add_point(struct drm_syncobj *syncobj,
   struct dma_fence *fence,
   uint64_t point)
 {
-   struct syncobj_wait_entry *cur, *tmp;
+   struct syncobj_wait_entry *wait_cur, *wait_tmp;
+   struct syncobj_eventfd_entry *ev_fd_cur, *ev_fd_tmp;
struct dma_fence *prev;
 
dma_fence_get(fence);
@@ -302,8 +339,10 @@ void 

Re: [PATCH v2] drm: split build lists one per line and sort

2022-10-12 Thread Jani Nikula
On Tue, 11 Oct 2022, Jani Nikula  wrote:
> While it takes more vertical space, sorted build lists with one object
> per line are arguably easier to manage, especially when there are
> conflicting changes.
>
> Split anything with more than one object file.
>
> v2: also split drm_cache.o and put it after drm_bridge.o (Andi)
>
> Signed-off-by: Jani Nikula 
> Reviewed-by: Andi Shyti 

Cc: drm-misc maintainers, don't really want to push this without an
approval from you guys.

BR,
Jani.

> ---
>  drivers/gpu/drm/Makefile | 107 ++-
>  drivers/gpu/drm/display/Makefile |  14 ++--
>  2 files changed, 85 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 25d0ba310509..6ad98d3ceff7 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -3,32 +3,71 @@
>  # Makefile for the drm device driver.  This driver provides support for the
>  # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>  
> -drm-y   :=   drm_aperture.o drm_auth.o drm_cache.o \
> - drm_file.o drm_gem.o drm_ioctl.o \
> - drm_drv.o \
> - drm_sysfs.o drm_mm.o \
> - drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o drm_displayid.o \
> - drm_trace_points.o drm_prime.o \
> - drm_vma_manager.o \
> - drm_modeset_lock.o drm_atomic.o drm_bridge.o \
> - drm_framebuffer.o drm_connector.o drm_blend.o \
> - drm_encoder.o drm_mode_object.o drm_property.o \
> - drm_plane.o drm_color_mgmt.o drm_print.o \
> - drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
> - drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
> - drm_client_modeset.o drm_atomic_uapi.o \
> - drm_managed.o drm_vblank_work.o
> -drm-$(CONFIG_DRM_LEGACY) += drm_agpsupport.o drm_bufs.o drm_context.o 
> drm_dma.o \
> - drm_hashtab.o drm_irq.o drm_legacy_misc.o 
> drm_lock.o \
> - drm_memory.o drm_scatter.o drm_vm.o
> +drm-y := \
> + drm_aperture.o \
> + drm_atomic.o \
> + drm_atomic_uapi.o \
> + drm_auth.o \
> + drm_blend.o \
> + drm_bridge.o \
> + drm_cache.o \
> + drm_client.o \
> + drm_client_modeset.o \
> + drm_color_mgmt.o \
> + drm_connector.o \
> + drm_crtc.o \
> + drm_displayid.o \
> + drm_drv.o \
> + drm_dumb_buffers.o \
> + drm_edid.o \
> + drm_encoder.o \
> + drm_file.o \
> + drm_fourcc.o \
> + drm_framebuffer.o \
> + drm_gem.o \
> + drm_ioctl.o \
> + drm_lease.o \
> + drm_managed.o \
> + drm_mm.o \
> + drm_mode_config.o \
> + drm_mode_object.o \
> + drm_modes.o \
> + drm_modeset_lock.o \
> + drm_plane.o \
> + drm_prime.o \
> + drm_print.o \
> + drm_property.o \
> + drm_syncobj.o \
> + drm_sysfs.o \
> + drm_trace_points.o \
> + drm_vblank.o \
> + drm_vblank_work.o \
> + drm_vma_manager.o \
> + drm_writeback.o
> +drm-$(CONFIG_DRM_LEGACY) += \
> + drm_agpsupport.o \
> + drm_bufs.o \
> + drm_context.o \
> + drm_dma.o \
> + drm_hashtab.o \
> + drm_irq.o \
> + drm_legacy_misc.o \
> + drm_lock.o \
> + drm_memory.o \
> + drm_scatter.o \
> + drm_vm.o
>  drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
>  drm-$(CONFIG_COMPAT) += drm_ioc32.o
>  drm-$(CONFIG_DRM_PANEL) += drm_panel.o
>  drm-$(CONFIG_OF) += drm_of.o
>  drm-$(CONFIG_PCI) += drm_pci.o
> -drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
> +drm-$(CONFIG_DEBUG_FS) += \
> + drm_debugfs.o \
> + drm_debugfs_crc.o
>  drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
> -drm-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o 
> drm_privacy_screen_x86.o
> +drm-$(CONFIG_DRM_PRIVACY_SCREEN) += \
> + drm_privacy_screen.o \
> + drm_privacy_screen_x86.o
>  obj-$(CONFIG_DRM)+= drm.o
>  
>  obj-$(CONFIG_DRM_NOMODESET) += drm_nomodeset.o
> @@ -57,16 +96,24 @@ obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
>  # Modesetting helpers
>  #
>  
> -drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o \
> - drm_encoder_slave.o drm_flip_work.o \
> - drm_probe_helper.o \
> - drm_plane_helper.o drm_atomic_helper.o \
> - drm_kms_helper_common.o \
> - drm_simple_kms_helper.o drm_modeset_helper.o \
> - drm_gem_atomic_helper.o \
> - drm_gem_framebuffer_helper.o \
> - drm_atomic_state_helper.o drm_damage_helper.o \
> - drm_format_helper.o drm_self_refresh_helper.o drm_rect.o
> +drm_kms_helper-y := \
> + drm_atomic_helper.o \
> + drm_atomic_state_helper.o \
> + drm_bridge_connector.o \
> + drm_crtc_helper.o \
> + drm_damage_helper.o \
> + drm_encoder_slave.o \
> + drm_flip_work.o \
> + drm_format_helper.o \
> + drm_gem_atomic_helper.o \

Re: [RFC PATCH v5 5/6] drm/tidss: Add IO CTRL and Power support for OLDI TX in am625

2022-10-12 Thread Tomi Valkeinen

On 28/09/2022 20:52, Aradhya Bhatia wrote:

The ctrl mmr module of the AM625 is different from the AM65X SoC. Thus
the ctrl mmr registers that supported the OLDI TX power have become
different in AM625 SoC.

Add IO CTRL support and control the OLDI TX power for AM625.

Signed-off-by: Aradhya Bhatia 
---
  drivers/gpu/drm/tidss/tidss_dispc.c  | 55 ++--
  drivers/gpu/drm/tidss/tidss_dispc_regs.h |  6 +++
  2 files changed, 49 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c 
b/drivers/gpu/drm/tidss/tidss_dispc.c
index 88008ad39b55..68444e0cd8d7 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.c
+++ b/drivers/gpu/drm/tidss/tidss_dispc.c
@@ -921,21 +921,52 @@ int dispc_vp_bus_check(struct dispc_device *dispc, u32 
hw_videoport,
  
  static void dispc_oldi_tx_power(struct dispc_device *dispc, bool power)

  {
-   u32 val = power ? 0 : OLDI_PWRDN_TX;
+   u32 val;
  
  	if (WARN_ON(!dispc->oldi_io_ctrl))

return;
  
-	regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT0_IO_CTRL,

-  OLDI_PWRDN_TX, val);
-   regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT1_IO_CTRL,
-  OLDI_PWRDN_TX, val);
-   regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT2_IO_CTRL,
-  OLDI_PWRDN_TX, val);
-   regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT3_IO_CTRL,
-  OLDI_PWRDN_TX, val);
-   regmap_update_bits(dispc->oldi_io_ctrl, OLDI_CLK_IO_CTRL,
-  OLDI_PWRDN_TX, val);
+   if (dispc->feat->subrev == DISPC_AM65X) {
+   val = power ? 0 : OLDI_PWRDN_TX;
+
+   regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT0_IO_CTRL,
+  OLDI_PWRDN_TX, val);
+   regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT1_IO_CTRL,
+  OLDI_PWRDN_TX, val);
+   regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT2_IO_CTRL,
+  OLDI_PWRDN_TX, val);
+   regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT3_IO_CTRL,
+  OLDI_PWRDN_TX, val);
+   regmap_update_bits(dispc->oldi_io_ctrl, OLDI_CLK_IO_CTRL,
+  OLDI_PWRDN_TX, val);
+
+   } else if (dispc->feat->subrev == DISPC_AM625) {
+   if (power) {
+   switch (dispc->oldi_mode) {
+   case OLDI_SINGLE_LINK_SINGLE_MODE:
+   /* Power down OLDI TX 1 */
+   val = OLDI1_PWRDN_TX;
+   break;
+
+   case OLDI_SINGLE_LINK_CLONE_MODE:
+   case OLDI_DUAL_LINK_MODE:
+   /* No Power down */
+   val = 0;
+   break;
+
+   default:
+   /* Power down both the OLDI TXes */
+   val = OLDI0_PWRDN_TX | OLDI1_PWRDN_TX;
+   break;
+   }
+   } else {
+   /* Power down both the OLDI TXes */
+   val = OLDI0_PWRDN_TX | OLDI1_PWRDN_TX;
+   }


Ugh, I hate power-down bits. So you "enable" it to disable it =). What's 
the default value or the register here? Or will this always be called? 
I.e. if we only use DPI, do we power down the OLDIs somewhere (or does 
it matter)?



+
+   regmap_update_bits(dispc->oldi_io_ctrl, OLDI_PD_CTRL,
+  OLDI0_PWRDN_TX | OLDI1_PWRDN_TX, val);
+   }
  }
  
  static void dispc_set_num_datalines(struct dispc_device *dispc,

@@ -2831,7 +2862,7 @@ int dispc_init(struct tidss_device *tidss)
dispc->vp_data[i].gamma_table = gamma_table;
}
  
-	if (feat->subrev == DISPC_AM65X) {

+   if (feat->subrev == DISPC_AM65X || feat->subrev == DISPC_AM625) {
r = dispc_init_am65x_oldi_io_ctrl(dev, dispc);
if (r)
return r;
diff --git a/drivers/gpu/drm/tidss/tidss_dispc_regs.h 
b/drivers/gpu/drm/tidss/tidss_dispc_regs.h
index 13feedfe5d6d..510bee70b3b8 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc_regs.h
+++ b/drivers/gpu/drm/tidss/tidss_dispc_regs.h
@@ -238,6 +238,12 @@ enum dispc_common_regs {
  #define OLDI_DAT3_IO_CTRL 0x0C
  #define OLDI_CLK_IO_CTRL  0x10
  
+/* Only for AM625 OLDI TX */

+#define OLDI_PD_CTRL   0x100
+#define OLDI_LB_CTRL   0x104
+
  #define OLDI_PWRDN_TX BIT(8)
+#define OLDI0_PWRDN_TX BIT(0)
+#define OLDI1_PWRDN_TX BIT(1)


Maybe these (the new and old ones) should be platform-prefixed. And 
organized so that the register and its bits are together.


 Tomi



Re: [RFC PATCH v5 4/6] drm/tidss: Add support to configure OLDI mode for am625-dss.

2022-10-12 Thread Tomi Valkeinen

On 28/09/2022 20:52, Aradhya Bhatia wrote:

The newer version of DSS (AM625-DSS) has 2 OLDI TXes at its disposal.
These can be configured to support the following modes:

1. OLDI_SINGLE_LINK_SINGLE_MODE
Single Output over OLDI 0.
+--++-+  +---+
|  || |  |   |
| CRTC +--->+ ENCODER +->| PANEL |
|  || |  |   |
+--++-+  +---+


Can you have single link on OLDI 1 (OLDI 0 off)? I don't know if that 
make sense on this platform, but if the pins for OLDI 0 and 1 are 
different, there might be a reason on some cases for that.



2. OLDI_SINGLE_LINK_CLONE_MODE
Duplicate Output over OLDI 0 and 1.
+--++-+  +---+
|  || |  |   |
| CRTC +---+--->| ENCODER +->| PANEL |
|  |   || |  |   |
+--+   |+-+  +---+
   |


I think you've got a tab in the line above, but otherwise use spaces.


|+-+  +---+
|| |  |   |
+--->| ENCODER +->| PANEL |
 | |  |   |
 +-+  +---+

3. OLDI_DUAL_LINK_MODE
Combined Output over OLDI 0 and 1.
+--++-+  +---+
|  || +->|   |
| CRTC +--->+ ENCODER |  | PANEL |
|  || +->|   |
+--++-+  +---+

Following the above pathways for different modes, 2 encoder/panel-bridge
pipes get created for clone mode, and 1 pipe in cases of single link and
dual link mode.

Add support for confgure the OLDI modes using of and lvds DRM helper


"configuring"


functions.

Signed-off-by: Aradhya Bhatia 
---
  drivers/gpu/drm/tidss/tidss_dispc.c |  11 +++
  drivers/gpu/drm/tidss/tidss_dispc.h |   8 ++
  drivers/gpu/drm/tidss/tidss_drv.h   |   3 +
  drivers/gpu/drm/tidss/tidss_kms.c   | 146 +++-
  4 files changed, 145 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c 
b/drivers/gpu/drm/tidss/tidss_dispc.c
index 34f0da4bb3e3..88008ad39b55 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.c
+++ b/drivers/gpu/drm/tidss/tidss_dispc.c
@@ -354,6 +354,8 @@ struct dispc_device {
  
  	bool is_enabled;
  
+	enum dispc_oldi_modes oldi_mode;

+
struct dss_vp_data vp_data[TIDSS_MAX_PORTS];
  
  	u32 *fourccs;

@@ -1958,6 +1960,15 @@ const u32 *dispc_plane_formats(struct dispc_device 
*dispc, unsigned int *len)
return dispc->fourccs;
  }
  
+int dispc_configure_oldi_mode(struct dispc_device *dispc,

+ enum dispc_oldi_modes oldi_mode)
+{
+   WARN_ON(!dispc);
+
+   dispc->oldi_mode = oldi_mode;
+   return 0;
+}


I think "configure" means more than just storing the value. Maybe 
dispc_set_oldi_mode(). And an empty line above the return.



+
  static s32 pixinc(int pixels, u8 ps)
  {
if (pixels == 1)
diff --git a/drivers/gpu/drm/tidss/tidss_dispc.h 
b/drivers/gpu/drm/tidss/tidss_dispc.h
index b66418e583ee..45cce1054832 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.h
+++ b/drivers/gpu/drm/tidss/tidss_dispc.h
@@ -64,6 +64,13 @@ enum dispc_dss_subrevision {
DISPC_AM625,
  };
  
+enum dispc_oldi_modes {

+   OLDI_MODE_OFF,  /* OLDI turned off / tied off 
in IP. */
+   OLDI_SINGLE_LINK_SINGLE_MODE,   /* Single Output over OLDI 0. */
+   OLDI_SINGLE_LINK_CLONE_MODE,/* Duplicate Output over OLDI 0 
and 1. */
+   OLDI_DUAL_LINK_MODE,/* Combined Output over OLDI 0 
and 1. */
+};
+
  struct dispc_features {
int min_pclk_khz;
int max_pclk_khz[DISPC_VP_MAX_BUS_TYPE];
@@ -131,6 +138,7 @@ int dispc_plane_setup(struct dispc_device *dispc, u32 
hw_plane,
  u32 hw_videoport);
  int dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable);
  const u32 *dispc_plane_formats(struct dispc_device *dispc, unsigned int *len);
+int dispc_configure_oldi_mode(struct dispc_device *dispc, enum 
dispc_oldi_modes oldi_mode);
  
  int dispc_init(struct tidss_device *tidss);

  void dispc_remove(struct tidss_device *tidss);
diff --git a/drivers/gpu/drm/tidss/tidss_drv.h 
b/drivers/gpu/drm/tidss/tidss_drv.h
index d7f27b0b0315..2252ba0222ca 100644
--- a/drivers/gpu/drm/tidss/tidss_drv.h
+++ b/drivers/gpu/drm/tidss/tidss_drv.h
@@ -12,6 +12,9 @@
  #define TIDSS_MAX_PORTS 4
  #define TIDSS_MAX_PLANES 4
  
+/* For AM625-DSS with 2 OLDI TXes */

+#define TIDSS_MAX_BRIDGE_PER_PIPE  2


"BRIDGES"?


+
  typedef u32 dispc_irq_t;
  
  struct tidss_device {

diff --git a/drivers/gpu/drm/tidss/tidss_kms.c 
b/drivers/gpu/drm/tidss/tidss_kms.c
index 666e527a0acf..73afe390f36d 100644
--- a/drivers/gpu/drm/tidss/tidss_kms.c
+++ b/drivers/gpu/drm/tidss/tidss_kms.c
@@ -107,32 +107,84 @@ static const struct drm_mode_config_funcs 
mode_config_funcs 

Re: [RFC PATCH v5 3/6] drm/tidss: Add support for AM625 DSS

2022-10-12 Thread Tomi Valkeinen

On 28/09/2022 20:52, Aradhya Bhatia wrote:

Add support for the DSS controller on TI's new AM625 SoC in the tidss
driver.

The first video port (VP0) in am625-dss can output OLDI signals through
2 OLDI TXes. A 3rd port has been added with "DISPC_VP_OLDI" bus type.

Signed-off-by: Aradhya Bhatia 
---
  drivers/gpu/drm/tidss/tidss_dispc.c | 61 -
  drivers/gpu/drm/tidss/tidss_dispc.h |  3 ++
  drivers/gpu/drm/tidss/tidss_drv.c   |  1 +
  3 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c 
b/drivers/gpu/drm/tidss/tidss_dispc.c
index dd3c6a606ae2..34f0da4bb3e3 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.c
+++ b/drivers/gpu/drm/tidss/tidss_dispc.c
@@ -93,6 +93,7 @@ const struct dispc_features dispc_k2g_feats = {
.common_regs = tidss_k2g_common_regs,
  
  	.num_vps = 1,

+   .num_max_ports = 1,
.vp_name = { "vp1" },
.ovr_name = { "ovr1" },
.vpclk_name =  { "vp1" },
@@ -168,6 +169,7 @@ const struct dispc_features dispc_am65x_feats = {
.common_regs = tidss_am65x_common_regs,
  
  	.num_vps = 2,

+   .num_max_ports = 2,
.vp_name = { "vp1", "vp2" },
.ovr_name = { "ovr1", "ovr2" },
.vpclk_name =  { "vp1", "vp2" },
@@ -257,6 +259,7 @@ const struct dispc_features dispc_j721e_feats = {
.common_regs = tidss_j721e_common_regs,
  
  	.num_vps = 4,

+   .num_max_ports = 4,
.vp_name = { "vp1", "vp2", "vp3", "vp4" },
.ovr_name = { "ovr1", "ovr2", "ovr3", "ovr4" },
.vpclk_name = { "vp1", "vp2", "vp3", "vp4" },
@@ -275,6 +278,57 @@ const struct dispc_features dispc_j721e_feats = {
.vid_order = { 1, 3, 0, 2 },
  };
  
+const struct dispc_features dispc_am625_feats = {

+   .max_pclk_khz = {
+   [DISPC_VP_DPI] = 165000,
+   [DISPC_VP_OLDI] = 165000,
+   },
+
+   .scaling = {
+   .in_width_max_5tap_rgb = 1280,
+   .in_width_max_3tap_rgb = 2560,
+   .in_width_max_5tap_yuv = 2560,
+   .in_width_max_3tap_yuv = 4096,
+   .upscale_limit = 16,
+   .downscale_limit_5tap = 4,
+   .downscale_limit_3tap = 2,
+   /*
+* The max supported pixel inc value is 255. The value
+* of pixel inc is calculated like this: 1+(xinc-1)*bpp.
+* The maximum bpp of all formats supported by the HW
+* is 8. So the maximum supported xinc value is 32,
+* because 1+(32-1)*8 < 255 < 1+(33-1)*4.
+*/
+   .xinc_max = 32,
+   },
+
+   .subrev = DISPC_AM625,
+
+   .common = "common",
+   .common_regs = tidss_am65x_common_regs,
+
+   .num_vps = 2,
+   /* note: the 3rd port is not representative of a 3rd pipeline */
+   .num_max_ports = 3,
+   .vp_name = { "vp1", "vp2" },
+   .ovr_name = { "ovr1", "ovr2" },
+   .vpclk_name =  { "vp1", "vp2" },
+   .vp_bus_type = { DISPC_VP_OLDI, DISPC_VP_DPI, DISPC_VP_OLDI },


Here, for example, we have an issue with the VP vs port. vp_bus_type is 
of size TIDSS_MAX_PORTS (VPs), but you're using it for output ports. If 
we did not have J7, which has 4 VPs, we'd have an overflow bug here.


The meaning of vp_sub_type also becomes a bit unclear. I guess it's 
rather "output_port_bus_type"?


 Tomi



Re: [PATCH v4 5/5] drm/ofdrm: Support big-endian scanout buffers

2022-10-12 Thread Michal Suchánek
On Wed, Oct 12, 2022 at 10:38:29AM +0200, Arnd Bergmann wrote:
> On Wed, Oct 12, 2022, at 10:27 AM, Thomas Zimmermann wrote:
> > Am 12.10.22 um 09:44 schrieb Arnd Bergmann:
> >> On Wed, Oct 12, 2022, at 9:40 AM, Thomas Zimmermann wrote:
> >>> Am 12.10.22 um 09:17 schrieb Arnd Bergmann:
>  On Wed, Oct 12, 2022, at 8:46 AM, Thomas Zimmermann wrote:
> >>>
>  Does qemu mark the device has having a particular endianess then, or
>  does it switch the layout of the framebuffer to match what the CPU
>  does?
> >>>
> >>> The latter. On neither architecture does qemu expose this flag. The
> >>> default endianess corresponds to the host.
> >> 
> >> "host" as in the machine that qemu runs on, or the machine that is
> >> being emulated? I suppose it would be broken either way, but in the
> >> latter case, we could get away with detecting that the machine is
> >> running under qemu.
> >
> > Sorry, my mistake. I meant "guest": the endianess of the framebuffer 
> > corresponds to the endianess of the emulated machine.  Given that many 
> > graphics cards support LE and BE modes, I assume that this behavior 
> > mimics real-hardware systems.
> 
> Not really: While the hardware may be able to switch between
> the modes, something has to actively set some hardware registers up
> that way, but the offb/ofdrm driver has no interface for interacting
> with that register, and the bootloader or firmware code that knows
> about the register has no information about what kernel it will
> eventually run. This is a bit architecture dependent, as e.g. on
> MIPS, a bi-endian hardware platform has to run a bootloader with the
> same endianness as the kernel, but on arm and powerpc the bootloader
> is usually fixed and the kernel switches to its configured endianness
> in the first few instructions after it gets entered.

But then the firmware knows that the kernel can switch endian and the
endian information should be provided. And maybe that should be emulated
better by qemu. Unfortunately, modern Power servers rarely come with a
graphics card so it's hard to test on real hardware.

Thanks

Michal


[PATCH v8 15/15] drm/msm/disp/dpu: clear active interface in the datapath cleanup

2022-10-12 Thread Vinod Polimera
Clear interface active register from the datapath for a clean shutdown of
the datapath.

Signed-off-by: Vinod Polimera 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 9f4f4e5..ab44016 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2069,6 +2069,9 @@ void dpu_encoder_helper_phys_cleanup(struct 
dpu_encoder_phys *phys_enc)
if (phys_enc->hw_pp->merge_3d)
intf_cfg.merge_3d = phys_enc->hw_pp->merge_3d->idx;
 
+   if (phys_enc->hw_intf)
+   intf_cfg.intf = phys_enc->hw_intf->idx;
+
if (ctl->ops.reset_intf_cfg)
ctl->ops.reset_intf_cfg(ctl, _cfg);
 
-- 
2.7.4



[PATCH v8 10/15] drm/msm/disp/dpu: check for crtc enable rather than crtc active to release shared resources

2022-10-12 Thread Vinod Polimera
According to KMS documentation, The driver must not release any shared
resources if active is set to false but enable still true.

Fixes: ccc862b957c6 ("drm/msm/dpu: Fix reservation failures in modeset")
Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 7e35560..e8c3518 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -648,7 +648,7 @@ static int dpu_encoder_virt_atomic_check(
if (drm_atomic_crtc_needs_modeset(crtc_state)) {
dpu_rm_release(global_state, drm_enc);
 
-   if (!crtc_state->active_changed || crtc_state->active)
+   if (!crtc_state->active_changed || crtc_state->enable)
ret = dpu_rm_reserve(_kms->rm, global_state,
drm_enc, crtc_state, topology);
}
-- 
2.7.4



[PATCH v8 07/15] drm/bridge: use atomic enable/disable callbacks for panel bridge

2022-10-12 Thread Vinod Polimera
Use atomic variants for panel bridge callback functions such that
certain states like self-refresh can be accessed as part of
enable/disable sequence.

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/bridge/panel.c | 20 
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 216af76..3558cbf 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -109,28 +109,32 @@ static void panel_bridge_detach(struct drm_bridge *bridge)
drm_connector_cleanup(connector);
 }
 
-static void panel_bridge_pre_enable(struct drm_bridge *bridge)
+static void panel_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+   struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
 
drm_panel_prepare(panel_bridge->panel);
 }
 
-static void panel_bridge_enable(struct drm_bridge *bridge)
+static void panel_bridge_atomic_enable(struct drm_bridge *bridge,
+   struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
 
drm_panel_enable(panel_bridge->panel);
 }
 
-static void panel_bridge_disable(struct drm_bridge *bridge)
+static void panel_bridge_atomic_disable(struct drm_bridge *bridge,
+   struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
 
drm_panel_disable(panel_bridge->panel);
 }
 
-static void panel_bridge_post_disable(struct drm_bridge *bridge)
+static void panel_bridge_atomic_post_disable(struct drm_bridge *bridge,
+   struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
 
@@ -159,10 +163,10 @@ static void panel_bridge_debugfs_init(struct drm_bridge 
*bridge,
 static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
.attach = panel_bridge_attach,
.detach = panel_bridge_detach,
-   .pre_enable = panel_bridge_pre_enable,
-   .enable = panel_bridge_enable,
-   .disable = panel_bridge_disable,
-   .post_disable = panel_bridge_post_disable,
+   .atomic_pre_enable = panel_bridge_atomic_pre_enable,
+   .atomic_enable = panel_bridge_atomic_enable,
+   .atomic_disable = panel_bridge_atomic_disable,
+   .atomic_post_disable = panel_bridge_atomic_post_disable,
.get_modes = panel_bridge_get_modes,
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
-- 
2.7.4



[PATCH v8 13/15] drm/msm/disp/dpu: wait for extra vsync till timing engine status is disabled

2022-10-12 Thread Vinod Polimera
There can be a race between timing gen disable and vblank irq. The
wait post timing gen disable may return early but intf disable sequence
might not be completed. Ensure that, intf status is disabled before
we retire the function.

Signed-off-by: Vinod Polimera 
---
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c| 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index 2c14646..5a0dc54 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -525,6 +525,7 @@ static void dpu_encoder_phys_vid_disable(struct 
dpu_encoder_phys *phys_enc)
 {
unsigned long lock_flags;
int ret;
+   struct intf_status intf_status = {0};
 
if (!phys_enc->parent || !phys_enc->parent->dev) {
DPU_ERROR("invalid encoder/device\n");
@@ -569,6 +570,26 @@ static void dpu_encoder_phys_vid_disable(struct 
dpu_encoder_phys *phys_enc)
}
}
 
+   if (phys_enc->hw_intf && phys_enc->hw_intf->ops.get_status)
+   phys_enc->hw_intf->ops.get_status(phys_enc->hw_intf, 
_status);
+
+   /*
+* Wait for a vsync if timing en status is on after timing engine
+* is disabled.
+*/
+   if (intf_status.is_en && dpu_encoder_phys_vid_is_master(phys_enc)) {
+   spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
+   dpu_encoder_phys_inc_pending(phys_enc);
+   spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
+   ret = dpu_encoder_phys_vid_wait_for_vblank(phys_enc);
+   if (ret) {
+   atomic_set(_enc->pending_kickoff_cnt, 0);
+   DRM_ERROR("wait disable failed: id:%u intf:%d ret:%d\n",
+ DRMID(phys_enc->parent),
+ phys_enc->hw_intf->idx - INTF_0, ret);
+   }
+   }
+
phys_enc->enable_state = DPU_ENC_DISABLED;
 }
 
-- 
2.7.4



[PATCH v8 08/15] drm/bridge: add psr support for panel bridge callbacks

2022-10-12 Thread Vinod Polimera
This change will handle the psr entry exit cases in the panel
bridge atomic callback functions. For example, the panel power
should not turn off if the panel is entering psr.

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Vinod Polimera 
---
 drivers/gpu/drm/bridge/panel.c | 48 ++
 1 file changed, 48 insertions(+)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 3558cbf..5e77e38 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -113,6 +113,18 @@ static void panel_bridge_atomic_pre_enable(struct 
drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
+   struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
+   struct drm_encoder *encoder = bridge->encoder;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *old_crtc_state;
+
+   crtc = drm_atomic_get_new_crtc_for_encoder(atomic_state, encoder);
+   if (!crtc)
+   return;
+
+   old_crtc_state = drm_atomic_get_old_crtc_state(atomic_state, crtc);
+   if (old_crtc_state && old_crtc_state->self_refresh_active)
+   return;
 
drm_panel_prepare(panel_bridge->panel);
 }
@@ -121,6 +133,18 @@ static void panel_bridge_atomic_enable(struct drm_bridge 
*bridge,
struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
+   struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
+   struct drm_encoder *encoder = bridge->encoder;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *old_crtc_state;
+
+   crtc = drm_atomic_get_new_crtc_for_encoder(atomic_state, encoder);
+   if (!crtc)
+   return;
+
+   old_crtc_state = drm_atomic_get_old_crtc_state(atomic_state, crtc);
+   if (old_crtc_state && old_crtc_state->self_refresh_active)
+   return;
 
drm_panel_enable(panel_bridge->panel);
 }
@@ -129,6 +153,18 @@ static void panel_bridge_atomic_disable(struct drm_bridge 
*bridge,
struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
+   struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
+   struct drm_encoder *encoder = bridge->encoder;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *new_crtc_state;
+
+   crtc = drm_atomic_get_old_crtc_for_encoder(atomic_state, encoder);
+   if (!crtc)
+   return;
+
+   new_crtc_state = drm_atomic_get_new_crtc_state(atomic_state, crtc);
+   if (new_crtc_state && new_crtc_state->self_refresh_active)
+   return;
 
drm_panel_disable(panel_bridge->panel);
 }
@@ -137,6 +173,18 @@ static void panel_bridge_atomic_post_disable(struct 
drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
 {
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
+   struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
+   struct drm_encoder *encoder = bridge->encoder;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *new_crtc_state;
+
+   crtc = drm_atomic_get_old_crtc_for_encoder(atomic_state, encoder);
+   if (!crtc)
+   return;
+
+   new_crtc_state = drm_atomic_get_new_crtc_state(atomic_state, crtc);
+   if (new_crtc_state && new_crtc_state->self_refresh_active)
+   return;
 
drm_panel_unprepare(panel_bridge->panel);
 }
-- 
2.7.4



[PATCH v8 06/15] drm/msm/dp: disable self_refresh_aware after entering psr

2022-10-12 Thread Vinod Polimera
From: Sankeerth Billakanti 

Updated frames get queued if self_refresh_aware is set when the
sink is in psr. To support bridge enable and avoid queuing of update
frames, reset the self_refresh_aware state after entering psr.

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Vinod Polimera 
---
 drivers/gpu/drm/msm/dp/dp_drm.c | 27 ++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 3e8912b..818c105 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -100,6 +100,8 @@ static void edp_bridge_atomic_enable(struct drm_bridge 
*drm_bridge,
struct drm_crtc_state *old_crtc_state;
struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
struct msm_dp *dp = dp_bridge->dp_display;
+   struct drm_connector *connector;
+   struct drm_connector_state *conn_state = NULL;
 
/*
 * Check the old state of the crtc to determine if the panel
@@ -116,10 +118,22 @@ static void edp_bridge_atomic_enable(struct drm_bridge 
*drm_bridge,
 
if (old_crtc_state && old_crtc_state->self_refresh_active) {
dp_display_set_psr(dp, false);
-   return;
+   goto psr_aware;
}
 
dp_bridge_atomic_enable(drm_bridge, old_bridge_state);
+
+psr_aware:
+   connector = drm_atomic_get_new_connector_for_encoder(atomic_state,
+   drm_bridge->encoder);
+   if (connector)
+   conn_state = drm_atomic_get_new_connector_state(atomic_state,
+   connector);
+
+   if (conn_state) {
+   conn_state->self_refresh_aware = dp->psr_supported;
+   }
+
 }
 
 static void edp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
@@ -130,6 +144,14 @@ static void edp_bridge_atomic_disable(struct drm_bridge 
*drm_bridge,
struct drm_crtc_state *new_crtc_state = NULL, *old_crtc_state = NULL;
struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
struct msm_dp *dp = dp_bridge->dp_display;
+   struct drm_connector *connector;
+   struct drm_connector_state *conn_state = NULL;
+
+   connector = drm_atomic_get_old_connector_for_encoder(atomic_state,
+   drm_bridge->encoder);
+   if (connector)
+   conn_state = drm_atomic_get_new_connector_state(atomic_state,
+   connector);
 
crtc = drm_atomic_get_old_crtc_for_encoder(atomic_state,
   drm_bridge->encoder);
@@ -156,6 +178,9 @@ static void edp_bridge_atomic_disable(struct drm_bridge 
*drm_bridge,
 * when display disable occurs while the sink is in psr state.
 */
if (new_crtc_state->self_refresh_active) {
+   if (conn_state)
+   conn_state->self_refresh_aware = false;
+
dp_display_set_psr(dp, true);
return;
} else if (old_crtc_state->self_refresh_active) {
-- 
2.7.4



[PATCH v8 04/15] drm/msm/dp: Add basic PSR support for eDP

2022-10-12 Thread Vinod Polimera
Add support for basic panel self refresh (PSR) feature for eDP.
Add a new interface to set PSR state in the sink from DPU.
Program the eDP controller to issue PSR enter and exit SDP to
the sink.

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_catalog.c |  80 ++
 drivers/gpu/drm/msm/dp/dp_catalog.h |   4 ++
 drivers/gpu/drm/msm/dp/dp_ctrl.c|  80 ++
 drivers/gpu/drm/msm/dp/dp_ctrl.h|   3 +
 drivers/gpu/drm/msm/dp/dp_display.c |  19 ++
 drivers/gpu/drm/msm/dp/dp_display.h |   2 +
 drivers/gpu/drm/msm/dp/dp_drm.c | 133 +++-
 drivers/gpu/drm/msm/dp/dp_link.c|  36 ++
 drivers/gpu/drm/msm/dp/dp_panel.c   |  22 ++
 drivers/gpu/drm/msm/dp/dp_panel.h   |   6 ++
 drivers/gpu/drm/msm/dp/dp_reg.h |  27 
 11 files changed, 411 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 676279d..c12a5d9 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -47,6 +47,14 @@
 #define DP_INTERRUPT_STATUS2_MASK \
(DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT)
 
+#define DP_INTERRUPT_STATUS4 \
+   (PSR_UPDATE_INT | PSR_CAPTURE_INT | PSR_EXIT_INT | \
+   PSR_UPDATE_ERROR_INT | PSR_WAKE_ERROR_INT)
+
+#define DP_INTERRUPT_MASK4 \
+   (PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \
+   PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK)
+
 struct dp_catalog_private {
struct device *dev;
struct drm_device *drm_dev;
@@ -359,6 +367,23 @@ void dp_catalog_ctrl_lane_mapping(struct dp_catalog 
*dp_catalog)
ln_mapping);
 }
 
+void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog,
+   bool enable)
+{
+   u32 val;
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+
+   val = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
+
+   if (enable)
+   val |= DP_MAINLINK_CTRL_ENABLE;
+   else
+   val &= ~DP_MAINLINK_CTRL_ENABLE;
+
+   dp_write_link(catalog, REG_DP_MAINLINK_CTRL, val);
+}
+
 void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog,
bool enable)
 {
@@ -610,6 +635,47 @@ void dp_catalog_ctrl_hpd_config(struct dp_catalog 
*dp_catalog)
dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, DP_DP_HPD_CTRL_HPD_EN);
 }
 
+static void dp_catalog_enable_sdp(struct dp_catalog_private *catalog)
+{
+   /* trigger sdp */
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, UPDATE_SDP);
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x0);
+}
+
+void dp_catalog_ctrl_config_psr(struct dp_catalog *dp_catalog)
+{
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+   u32 config;
+
+   /* enable PSR1 function */
+   config = dp_read_link(catalog, REG_PSR_CONFIG);
+   config |= PSR1_SUPPORTED;
+   dp_write_link(catalog, REG_PSR_CONFIG, config);
+
+   dp_write_ahb(catalog, REG_DP_INTR_MASK4, DP_INTERRUPT_MASK4);
+   dp_catalog_enable_sdp(catalog);
+}
+
+void dp_catalog_ctrl_set_psr(struct dp_catalog *dp_catalog, bool enter)
+{
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+   u32 cmd;
+
+   cmd = dp_read_link(catalog, REG_PSR_CMD);
+
+   cmd &= ~(PSR_ENTER | PSR_EXIT);
+
+   if (enter)
+   cmd |= PSR_ENTER;
+   else
+   cmd |= PSR_EXIT;
+
+   dp_catalog_enable_sdp(catalog);
+   dp_write_link(catalog, REG_PSR_CMD, cmd);
+}
+
 u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog)
 {
struct dp_catalog_private *catalog = container_of(dp_catalog,
@@ -645,6 +711,20 @@ u32 dp_catalog_hpd_get_intr_status(struct dp_catalog 
*dp_catalog)
return isr & (mask | ~DP_DP_HPD_INT_MASK);
 }
 
+u32 dp_catalog_ctrl_read_psr_interrupt_status(struct dp_catalog *dp_catalog)
+{
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+   u32 intr, intr_ack;
+
+   intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS4);
+   intr_ack = (intr & DP_INTERRUPT_STATUS4)
+   << DP_INTERRUPT_STATUS_ACK_SHIFT;
+   dp_write_ahb(catalog, REG_DP_INTR_STATUS4, intr_ack);
+
+   return intr;
+}
+
 int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog)
 {
struct dp_catalog_private *catalog = container_of(dp_catalog,
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h 
b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 1f717f4..2174bb5 100644
--- 

[PATCH v8 05/15] drm/msm/dp: use the eDP bridge ops to validate eDP modes

2022-10-12 Thread Vinod Polimera
The eDP and DP interfaces shared the bridge operations and
the eDP specific changes were implemented under is_edp check.
To add psr support for eDP, we started using a new set of eDP
bridge ops. We are moving the eDP specific code in the
dp_bridge_mode_valid function to a new eDP function,
edp_bridge_mode_valid under the eDP bridge ops.

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_display.c |  8 
 drivers/gpu/drm/msm/dp/dp_drm.c | 34 +-
 2 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 5f2aae4..e481099 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -984,14 +984,6 @@ enum drm_mode_status dp_bridge_mode_valid(struct 
drm_bridge *bridge,
return -EINVAL;
}
 
-   /*
-* The eDP controller currently does not have a reliable way of
-* enabling panel power to read sink capabilities. So, we rely
-* on the panel driver to populate only supported modes for now.
-*/
-   if (dp->is_edp)
-   return MODE_OK;
-
if (mode->clock > DP_MAX_PIXEL_CLK_KHZ)
return MODE_CLOCK_HIGH;
 
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index a3491d2..3e8912b 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -192,12 +192,44 @@ static void edp_bridge_atomic_post_disable(struct 
drm_bridge *drm_bridge,
dp_bridge_atomic_post_disable(drm_bridge, old_bridge_state);
 }
 
+/**
+ * edp_bridge_mode_valid - callback to determine if specified mode is valid
+ * @bridge: Pointer to drm bridge structure
+ * @info: display info
+ * @mode: Pointer to drm mode structure
+ * Returns: Validity status for specified mode
+ */
+static enum drm_mode_status edp_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_info *info,
+ const struct drm_display_mode *mode)
+{
+   struct msm_dp *dp;
+   int mode_pclk_khz = mode->clock;
+
+   dp = to_dp_bridge(bridge)->dp_display;
+
+   if (!dp || !mode_pclk_khz || !dp->connector) {
+   DRM_ERROR("invalid params\n");
+   return -EINVAL;
+   }
+
+   if (mode->clock > DP_MAX_PIXEL_CLK_KHZ)
+   return MODE_CLOCK_HIGH;
+
+   /*
+* The eDP controller currently does not have a reliable way of
+* enabling panel power to read sink capabilities. So, we rely
+* on the panel driver to populate only supported modes for now.
+*/
+   return MODE_OK;
+}
+
 static const struct drm_bridge_funcs edp_bridge_ops = {
.atomic_enable = edp_bridge_atomic_enable,
.atomic_disable = edp_bridge_atomic_disable,
.atomic_post_disable = edp_bridge_atomic_post_disable,
.mode_set = dp_bridge_mode_set,
-   .mode_valid = dp_bridge_mode_valid,
+   .mode_valid = edp_bridge_mode_valid,
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
-- 
2.7.4



[PATCH v8 09/15] drm/msm/disp/dpu: use atomic enable/disable callbacks for encoder functions

2022-10-12 Thread Vinod Polimera
Use atomic variants for encoder callback functions such that
certain states like self-refresh can be accessed as part of
enable/disable sequence.

Signed-off-by: Kalyan Thota 
Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index d05b353..7e35560 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1167,7 +1167,8 @@ void dpu_encoder_virt_runtime_resume(struct drm_encoder 
*drm_enc)
mutex_unlock(_enc->enc_lock);
 }
 
-static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc)
+static void dpu_encoder_virt_atomic_enable(struct drm_encoder *drm_enc,
+   struct drm_atomic_state *state)
 {
struct dpu_encoder_virt *dpu_enc = NULL;
int ret = 0;
@@ -1203,7 +1204,8 @@ static void dpu_encoder_virt_enable(struct drm_encoder 
*drm_enc)
mutex_unlock(_enc->enc_lock);
 }
 
-static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
+static void dpu_encoder_virt_atomic_disable(struct drm_encoder *drm_enc,
+   struct drm_atomic_state *state)
 {
struct dpu_encoder_virt *dpu_enc = NULL;
int i = 0;
@@ -2378,8 +2380,8 @@ static void dpu_encoder_frame_done_timeout(struct 
timer_list *t)
 
 static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = {
.atomic_mode_set = dpu_encoder_virt_atomic_mode_set,
-   .disable = dpu_encoder_virt_disable,
-   .enable = dpu_encoder_virt_enable,
+   .atomic_disable = dpu_encoder_virt_atomic_disable,
+   .atomic_enable = dpu_encoder_virt_atomic_enable,
.atomic_check = dpu_encoder_virt_atomic_check,
 };
 
-- 
2.7.4



[PATCH v8 12/15] drm/msm/disp/dpu: get timing engine status from intf status register

2022-10-12 Thread Vinod Polimera
Timing gen status can be read reliablly from intf status
register rather than from the timing gen control register,
which will readback as "0" after disable though the timing
gen is still under going disable path. This support was
added from DPU version 5.0.0.

Signed-off-by: Vinod Polimera 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c |  3 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 12 +++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c|  8 +++-
 3 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 27f029f..0332cea 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -77,7 +77,8 @@
 
 #define INTF_SC7180_MASK BIT(DPU_INTF_INPUT_CTRL) | BIT(DPU_INTF_TE)
 
-#define INTF_SC7280_MASK INTF_SC7180_MASK | BIT(DPU_DATA_HCTL_EN)
+#define INTF_SC7280_MASK \
+   (INTF_SC7180_MASK | BIT(DPU_DATA_HCTL_EN) | 
BIT(DPU_INTF_STATUS_SUPPORTED))
 
 #define IRQ_SDM845_MASK (BIT(MDP_SSPP_TOP0_INTR) | \
 BIT(MDP_SSPP_TOP0_INTR2) | \
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 38aa38a..21ae3cf 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -203,17 +203,19 @@ enum {
 
 /**
  * INTF sub-blocks
- * @DPU_INTF_INPUT_CTRL Supports the setting of pp block from which
- *  pixel data arrives to this INTF
- * @DPU_INTF_TE INTF block has TE configuration support
- * @DPU_DATA_HCTL_ENAllows data to be transferred at different rate
-than video timing
+ * @DPU_INTF_INPUT_CTRL Supports the setting of pp block from which
+ *  pixel data arrives to this INTF
+ * @DPU_INTF_TE INTF block has TE configuration support
+ * @DPU_DATA_HCTL_ENAllows data to be transferred at different 
rate
+   than video timing
+ * @DPU_INTF_STATUS_SUPPORTED   INTF block has INTF_STATUS register
  * @DPU_INTF_MAX
  */
 enum {
DPU_INTF_INPUT_CTRL = 0x1,
DPU_INTF_TE,
DPU_DATA_HCTL_EN,
+   DPU_INTF_STATUS_SUPPORTED,
DPU_INTF_MAX
 };
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
index 7ce66bf..2394473 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
@@ -62,6 +62,7 @@
 #define   INTF_LINE_COUNT   0x0B0
 
 #define   INTF_MUX  0x25C
+#define   INTF_STATUS   0x26C
 
 #define INTF_CFG_ACTIVE_H_EN   BIT(29)
 #define INTF_CFG_ACTIVE_V_EN   BIT(30)
@@ -297,8 +298,13 @@ static void dpu_hw_intf_get_status(
struct intf_status *s)
 {
struct dpu_hw_blk_reg_map *c = >hw;
+   unsigned long cap = intf->cap->features;
+
+   if (cap & BIT(DPU_INTF_STATUS_SUPPORTED))
+   s->is_en = BIT(0) & DPU_REG_READ(c, INTF_STATUS);
+   else
+   s->is_en = DPU_REG_READ(c, INTF_TIMING_ENGINE_EN);
 
-   s->is_en = DPU_REG_READ(c, INTF_TIMING_ENGINE_EN);
s->is_prog_fetch_en = !!(DPU_REG_READ(c, INTF_CONFIG) & BIT(31));
if (s->is_en) {
s->frame_count = DPU_REG_READ(c, INTF_FRAME_COUNT);
-- 
2.7.4



[PATCH v8 14/15] drm/msm/disp/dpu: reset the datapath after timing engine disable

2022-10-12 Thread Vinod Polimera
Reset the datapath after disabling the timing gen, such that
it can start on a clean slate when the intf is enabled back.
This was a recommended sequence from the DPU HW programming guide.

Signed-off-by: Vinod Polimera 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index 5a0dc54..aeeb759 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -590,6 +590,7 @@ static void dpu_encoder_phys_vid_disable(struct 
dpu_encoder_phys *phys_enc)
}
}
 
+   dpu_encoder_helper_phys_cleanup(phys_enc);
phys_enc->enable_state = DPU_ENC_DISABLED;
 }
 
-- 
2.7.4



[PATCH v8 01/15] drm/msm/disp/dpu: clear dpu_assign_crtc and get crtc from connector state instead of dpu_enc

2022-10-12 Thread Vinod Polimera
Update crtc retrieval from dpu_enc to dpu_enc connector state,
since new links get set as part of the dpu enc virt mode set.
The dpu_enc->crtc cache is no more needed, hence cleaning it as
part of this change.

Signed-off-by: Vinod Polimera 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c|  4 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 42 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  8 --
 3 files changed, 13 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 13ce321..8ec9a13 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1029,7 +1029,6 @@ static void dpu_crtc_disable(struct drm_crtc *crtc,
 */
if (dpu_encoder_get_intf_mode(encoder) == INTF_MODE_VIDEO)
release_bandwidth = true;
-   dpu_encoder_assign_crtc(encoder, NULL);
}
 
/* wait for frame_event_done completion */
@@ -1099,9 +1098,6 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
trace_dpu_crtc_enable(DRMID(crtc), true, dpu_crtc);
dpu_crtc->enabled = true;
 
-   drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask)
-   dpu_encoder_assign_crtc(encoder, crtc);
-
/* Enable/restore vblank irq handling */
drm_crtc_vblank_on(crtc);
 }
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 9c6817b..d05b353 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -132,11 +132,6 @@ enum dpu_enc_rc_states {
  * @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
- * @crtc:  Pointer to the currently assigned crtc. Normally you
- * would use crtc->state->encoder_mask to determine the
- * link between encoder/crtc. However in this case we need
- * to track crtc in the disable() hook which is called
- * _after_ encoder_mask is cleared.
  * @connector: If a mode is set, cached pointer to the active connector
  * @crtc_kickoff_cb:   Callback into CRTC that will flush & start
  * all CTL paths
@@ -181,7 +176,6 @@ struct dpu_encoder_virt {
 
bool intfs_swapped;
 
-   struct drm_crtc *crtc;
struct drm_connector *connector;
 
struct dentry *debugfs_root;
@@ -1288,7 +1282,7 @@ static void dpu_encoder_vblank_callback(struct 
drm_encoder *drm_enc,
struct dpu_encoder_phys *phy_enc)
 {
struct dpu_encoder_virt *dpu_enc = NULL;
-   unsigned long lock_flags;
+   struct drm_crtc *crtc;
 
if (!drm_enc || !phy_enc)
return;
@@ -1296,12 +1290,13 @@ static void dpu_encoder_vblank_callback(struct 
drm_encoder *drm_enc,
DPU_ATRACE_BEGIN("encoder_vblank_callback");
dpu_enc = to_dpu_encoder_virt(drm_enc);
 
-   atomic_inc(_enc->vsync_cnt);
+   if (!dpu_enc->connector || !dpu_enc->connector->state ||
+   !dpu_enc->connector->state->crtc)
+   return;
 
-   spin_lock_irqsave(_enc->enc_spinlock, lock_flags);
-   if (dpu_enc->crtc)
-   dpu_crtc_vblank_callback(dpu_enc->crtc);
-   spin_unlock_irqrestore(_enc->enc_spinlock, lock_flags);
+   atomic_inc(_enc->vsync_cnt);
+   crtc = dpu_enc->connector->state->crtc;
+   dpu_crtc_vblank_callback(crtc);
 
DPU_ATRACE_END("encoder_vblank_callback");
 }
@@ -1324,33 +1319,22 @@ static void dpu_encoder_underrun_callback(struct 
drm_encoder *drm_enc,
DPU_ATRACE_END("encoder_underrun_callback");
 }
 
-void dpu_encoder_assign_crtc(struct drm_encoder *drm_enc, struct drm_crtc 
*crtc)
-{
-   struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
-   unsigned long lock_flags;
-
-   spin_lock_irqsave(_enc->enc_spinlock, lock_flags);
-   /* crtc should always be cleared before re-assigning */
-   WARN_ON(crtc && dpu_enc->crtc);
-   dpu_enc->crtc = crtc;
-   spin_unlock_irqrestore(_enc->enc_spinlock, lock_flags);
-}
-
 void dpu_encoder_toggle_vblank_for_crtc(struct drm_encoder *drm_enc,
struct drm_crtc *crtc, bool enable)
 {
struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
-   unsigned long lock_flags;
+   struct drm_crtc *new_crtc;
int i;
 
trace_dpu_enc_vblank_cb(DRMID(drm_enc), enable);
 
-   spin_lock_irqsave(_enc->enc_spinlock, lock_flags);
-   if (dpu_enc->crtc != crtc) {
-   spin_unlock_irqrestore(_enc->enc_spinlock, lock_flags);
+   if (!dpu_enc->connector || 

[PATCH v8 11/15] drm/msm/disp/dpu: add PSR support for eDP interface in dpu driver

2022-10-12 Thread Vinod Polimera
Enable PSR on eDP interface using drm self-refresh librabry.
This patch uses a trigger from self-refresh library to enter/exit
into PSR, when there are no updates from framework.

Signed-off-by: Kalyan Thota 
Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c| 13 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 14 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  2 +-
 3 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 8ec9a13..5ba4963 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "dpu_kms.h"
 #include "dpu_hw_lm.h"
@@ -1018,6 +1019,9 @@ static void dpu_crtc_disable(struct drm_crtc *crtc,
 
DRM_DEBUG_KMS("crtc%d\n", crtc->base.id);
 
+   if (old_crtc_state->self_refresh_active)
+   return;
+
/* Disable/save vblank irq handling */
drm_crtc_vblank_off(crtc);
 
@@ -1572,7 +1576,7 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, 
struct drm_plane *plane,
 {
struct drm_crtc *crtc = NULL;
struct dpu_crtc *dpu_crtc = NULL;
-   int i;
+   int i, ret;
 
dpu_crtc = kzalloc(sizeof(*dpu_crtc), GFP_KERNEL);
if (!dpu_crtc)
@@ -1609,6 +1613,13 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, 
struct drm_plane *plane,
/* initialize event handling */
spin_lock_init(_crtc->event_lock);
 
+   ret = drm_self_refresh_helper_init(crtc);
+   if (ret) {
+   DPU_ERROR("Failed to initialize %s with self-refresh helpers 
%d\n",
+   crtc->name, ret);
+   return ERR_PTR(ret);
+   }
+
DRM_DEBUG_KMS("%s: successfully initialized crtc\n", dpu_crtc->name);
return crtc;
 }
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index e8c3518..9f4f4e5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -1208,11 +1209,24 @@ static void dpu_encoder_virt_atomic_disable(struct 
drm_encoder *drm_enc,
struct drm_atomic_state *state)
 {
struct dpu_encoder_virt *dpu_enc = NULL;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *old_state = NULL;
int i = 0;
 
dpu_enc = to_dpu_encoder_virt(drm_enc);
DPU_DEBUG_ENC(dpu_enc, "\n");
 
+   crtc = drm_atomic_get_old_crtc_for_encoder(state, drm_enc);
+   if (crtc)
+   old_state = drm_atomic_get_old_crtc_state(state, crtc);
+
+   /*
+* The encoder is already disabled if self refresh mode was set earlier,
+* in the old_state for the corresponding crtc.
+*/
+   if (old_state && old_state->self_refresh_active)
+   return;
+
mutex_lock(_enc->enc_lock);
dpu_enc->enabled = false;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 5e6e262..0247f39 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -503,7 +503,7 @@ static void dpu_kms_wait_for_commit_done(struct msm_kms 
*kms,
return;
}
 
-   if (!crtc->state->active) {
+   if (!drm_atomic_crtc_effectively_active(crtc->state)) {
DPU_DEBUG("[crtc:%d] not active\n", crtc->base.id);
return;
}
-- 
2.7.4



[PATCH v8 00/15] Add PSR support for eDP

2022-10-12 Thread Vinod Polimera
Changes in v2:
  - Use dp bridge to set psr entry/exit instead of dpu_enocder.
  - Don't modify whitespaces.
  - Set self refresh aware from atomic_check.
  - Set self refresh aware only if psr is supported.
  - Provide a stub for msm_dp_display_set_psr.
  - Move dp functions to bridge code.

Changes in v3:
  - Change callback names to reflect atomic interfaces.
  - Move bridge callback change to separate patch as suggested by Dmitry.
  - Remove psr function declaration from msm_drv.h.
  - Set self_refresh_aware flag only if psr is supported.
  - Modify the variable names to simpler form.
  - Define bit fields for PSR settings.
  - Add comments explaining the steps to enter/exit psr.
  - Change DRM_INFO to drm_dbg_db. 

Changes in v4:
  - Move the get crtc functions to drm_atomic.
  - Add atomic functions for DP bridge too.
  - Add ternary operator to choose eDP or DP ops.
  - Return true/false instead of 1/0.
  - mode_valid missing in the eDP bridge ops.
  - Move the functions to get crtc into drm_atomic.c.
  - Fix compilation issues.
  - Remove dpu_assign_crtc and get crtc from drm_enc instead of dpu_enc.
  - Check for crtc state enable while reserving resources.

Changes in v5:
  - Move the mode_valid changes into a different patch.
  - Complete psr_op_comp only when isr is set.
  - Move the DP atomic callback changes to a different patch.
  - Get crtc from drm connector state crtc.
  - Move to separate patch for check for crtc state enable while
reserving resources.

Changes in v6:
  - Remove crtc from dpu_encoder_virt struct.
  - fix crtc check during vblank toggle crtc.
  - Misc changes. 

Changes in v7:
  - Add fix for underrun issue on kasan build.

Changes in v8:
  - Drop the enc spinlock as it won't serve any purpose in
protetcing conn state.(Dmitry/Doug)

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Kalyan Thota 
Signed-off-by: Vinod Polimera 

Sankeerth Billakanti (1):
  drm/msm/dp: disable self_refresh_aware after entering psr

Vinod Polimera (14):
  drm/msm/disp/dpu: clear dpu_assign_crtc and get crtc from connector
state instead of dpu_enc
  drm: add helper functions to retrieve old and new crtc
  drm/msm/dp: use atomic callbacks for DP bridge ops
  drm/msm/dp: Add basic PSR support for eDP
  drm/msm/dp: use the eDP bridge ops to validate eDP modes
  drm/bridge: use atomic enable/disable callbacks for panel bridge
  drm/bridge: add psr support for panel bridge callbacks
  drm/msm/disp/dpu: use atomic enable/disable callbacks for encoder
functions
  drm/msm/disp/dpu: check for crtc enable rather than crtc active to
release shared resources
  drm/msm/disp/dpu: add PSR support for eDP interface in dpu driver
  drm/msm/disp/dpu: get timing engine status from intf status register
  drm/msm/disp/dpu: wait for extra vsync till timing engine status is
disabled
  drm/msm/disp/dpu: reset the datapath after timing engine disable
  drm/msm/disp/dpu: clear active interface in the datapath cleanup

 drivers/gpu/drm/bridge/panel.c |  68 ++-
 drivers/gpu/drm/drm_atomic.c   |  60 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c   |  17 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c|  71 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h|   8 -
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c   |  22 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c |   3 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h |  12 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c|   8 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c|   2 +-
 drivers/gpu/drm/msm/dp/dp_catalog.c|  80 
 drivers/gpu/drm/msm/dp/dp_catalog.h|   4 +
 drivers/gpu/drm/msm/dp/dp_ctrl.c   |  80 
 drivers/gpu/drm/msm/dp/dp_ctrl.h   |   3 +
 drivers/gpu/drm/msm/dp/dp_display.c|  36 ++--
 drivers/gpu/drm/msm/dp/dp_display.h|   2 +
 drivers/gpu/drm/msm/dp/dp_drm.c| 207 -
 drivers/gpu/drm/msm/dp/dp_drm.h|   9 +-
 drivers/gpu/drm/msm/dp/dp_link.c   |  36 
 drivers/gpu/drm/msm/dp/dp_panel.c  |  22 +++
 drivers/gpu/drm/msm/dp/dp_panel.h  |   6 +
 drivers/gpu/drm/msm/dp/dp_reg.h|  27 +++
 include/drm/drm_atomic.h   |   7 +
 23 files changed, 705 insertions(+), 85 deletions(-)

-- 
2.7.4



[PATCH v8 02/15] drm: add helper functions to retrieve old and new crtc

2022-10-12 Thread Vinod Polimera
Add new helper functions, drm_atomic_get_old_crtc_for_encoder
and drm_atomic_get_new_crtc_for_encoder to retrieve the
corresponding crtc for the encoder.

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Vinod Polimera 
Reviewed-by: Douglas Anderson 
---
 drivers/gpu/drm/drm_atomic.c | 60 
 include/drm/drm_atomic.h |  7 ++
 2 files changed, 67 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index f197f59..941fd6d 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -985,6 +985,66 @@ drm_atomic_get_new_connector_for_encoder(struct 
drm_atomic_state *state,
 EXPORT_SYMBOL(drm_atomic_get_new_connector_for_encoder);
 
 /**
+ * drm_atomic_get_old_crtc_for_encoder - Get old crtc for an encoder
+ * @state: Atomic state
+ * @encoder: The encoder to fetch the crtc state for
+ *
+ * This function finds and returns the crtc that was connected to @encoder
+ * as specified by the @state.
+ *
+ * Returns: The old crtc connected to @encoder, or NULL if the encoder is
+ * not connected.
+ */
+struct drm_crtc *
+drm_atomic_get_old_crtc_for_encoder(struct drm_atomic_state *state,
+   struct drm_encoder *encoder)
+{
+   struct drm_connector *connector;
+   struct drm_connector_state *conn_state;
+
+   connector = drm_atomic_get_old_connector_for_encoder(state, encoder);
+   if (!connector)
+   return NULL;
+
+   conn_state = drm_atomic_get_old_connector_state(state, connector);
+   if (!conn_state)
+   return NULL;
+
+   return conn_state->crtc;
+}
+EXPORT_SYMBOL(drm_atomic_get_old_crtc_for_encoder);
+
+/**
+ * drm_atomic_get_new_crtc_for_encoder - Get new crtc for an encoder
+ * @state: Atomic state
+ * @encoder: The encoder to fetch the crtc state for
+ *
+ * This function finds and returns the crtc that will be connected to @encoder
+ * as specified by the @state.
+ *
+ * Returns: The new crtc connected to @encoder, or NULL if the encoder is
+ * not connected.
+ */
+struct drm_crtc *
+drm_atomic_get_new_crtc_for_encoder(struct drm_atomic_state *state,
+   struct drm_encoder *encoder)
+{
+   struct drm_connector *connector;
+   struct drm_connector_state *conn_state;
+
+   connector = drm_atomic_get_new_connector_for_encoder(state, encoder);
+   if (!connector)
+   return NULL;
+
+   conn_state = drm_atomic_get_new_connector_state(state, connector);
+   if (!conn_state)
+   return NULL;
+
+   return conn_state->crtc;
+}
+EXPORT_SYMBOL(drm_atomic_get_new_crtc_for_encoder);
+
+/**
  * drm_atomic_get_connector_state - get connector state
  * @state: global atomic state object
  * @connector: connector to get state object for
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 10b1990..fdbd656 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -528,6 +528,13 @@ struct drm_connector *
 drm_atomic_get_new_connector_for_encoder(struct drm_atomic_state *state,
 struct drm_encoder *encoder);
 
+struct drm_crtc *
+drm_atomic_get_old_crtc_for_encoder(struct drm_atomic_state *state,
+struct drm_encoder *encoder);
+struct drm_crtc *
+drm_atomic_get_new_crtc_for_encoder(struct drm_atomic_state *state,
+struct drm_encoder *encoder);
+
 /**
  * drm_atomic_get_existing_crtc_state - get CRTC state, if it exists
  * @state: global atomic state object
-- 
2.7.4



[PATCH v8 03/15] drm/msm/dp: use atomic callbacks for DP bridge ops

2022-10-12 Thread Vinod Polimera
Use atomic variants for DP bridge callback functions so that
the atomic state can be accessed in the interface drivers.
The atomic state will help the driver find out if the display
is in self refresh state.

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Vinod Polimera 
Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Douglas Anderson 
---
 drivers/gpu/drm/msm/dp/dp_display.c |  9 ++---
 drivers/gpu/drm/msm/dp/dp_drm.c | 17 ++---
 drivers/gpu/drm/msm/dp/dp_drm.h |  9 ++---
 3 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index bfd0aef..bfffc2b 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1636,7 +1636,8 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct 
drm_device *dev,
return 0;
 }
 
-void dp_bridge_enable(struct drm_bridge *drm_bridge)
+void dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
+struct drm_bridge_state *old_bridge_state)
 {
struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
struct msm_dp *dp = dp_bridge->dp_display;
@@ -1691,7 +1692,8 @@ void dp_bridge_enable(struct drm_bridge *drm_bridge)
mutex_unlock(_display->event_mutex);
 }
 
-void dp_bridge_disable(struct drm_bridge *drm_bridge)
+void dp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
+ struct drm_bridge_state *old_bridge_state)
 {
struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
struct msm_dp *dp = dp_bridge->dp_display;
@@ -1702,7 +1704,8 @@ void dp_bridge_disable(struct drm_bridge *drm_bridge)
dp_ctrl_push_idle(dp_display->ctrl);
 }
 
-void dp_bridge_post_disable(struct drm_bridge *drm_bridge)
+void dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
+  struct drm_bridge_state *old_bridge_state)
 {
struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
struct msm_dp *dp = dp_bridge->dp_display;
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 6df25f7..43ce208 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -61,13 +61,16 @@ static int dp_bridge_get_modes(struct drm_bridge *bridge, 
struct drm_connector *
 }
 
 static const struct drm_bridge_funcs dp_bridge_ops = {
-   .enable   = dp_bridge_enable,
-   .disable  = dp_bridge_disable,
-   .post_disable = dp_bridge_post_disable,
-   .mode_set = dp_bridge_mode_set,
-   .mode_valid   = dp_bridge_mode_valid,
-   .get_modes= dp_bridge_get_modes,
-   .detect   = dp_bridge_detect,
+   .atomic_enable = dp_bridge_atomic_enable,
+   .atomic_disable = dp_bridge_atomic_disable,
+   .atomic_post_disable = dp_bridge_atomic_post_disable,
+   .mode_set = dp_bridge_mode_set,
+   .mode_valid = dp_bridge_mode_valid,
+   .get_modes = dp_bridge_get_modes,
+   .detect = dp_bridge_detect,
+   .atomic_reset = drm_atomic_helper_bridge_reset,
+   .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+   .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
 };
 
 struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device 
*dev,
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h
index 82035db..e69c0b9 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.h
+++ b/drivers/gpu/drm/msm/dp/dp_drm.h
@@ -23,9 +23,12 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp 
*dp_display, struct dr
 struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device 
*dev,
struct drm_encoder *encoder);
 
-void dp_bridge_enable(struct drm_bridge *drm_bridge);
-void dp_bridge_disable(struct drm_bridge *drm_bridge);
-void dp_bridge_post_disable(struct drm_bridge *drm_bridge);
+void dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
+struct drm_bridge_state *old_bridge_state);
+void dp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
+ struct drm_bridge_state *old_bridge_state);
+void dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
+  struct drm_bridge_state *old_bridge_state);
 enum drm_mode_status dp_bridge_mode_valid(struct drm_bridge *bridge,
  const struct drm_display_info *info,
  const struct drm_display_mode *mode);
-- 
2.7.4



RE: [PATCH v7 01/15] drm/msm/disp/dpu: clear dpu_assign_crtc and get crtc from connector state instead of dpu_enc

2022-10-12 Thread Vinod Polimera


> -Original Message-
> From: Dmitry Baryshkov 
> Sent: Tuesday, September 13, 2022 10:36 PM
> To: Vinod Polimera (QUIC) ; dri-
> de...@lists.freedesktop.org; linux-arm-...@vger.kernel.org;
> freedr...@lists.freedesktop.org; devicet...@vger.kernel.org
> Cc: linux-ker...@vger.kernel.org; robdcl...@gmail.com;
> diand...@chromium.org; swb...@chromium.org; Kalyan Thota (QUIC)
> ; Kuogee Hsieh (QUIC)
> ; Vishnuvardhan Prodduturi (QUIC)
> ; Bjorn Andersson (QUIC)
> ; Aravind Venkateswaran (QUIC)
> ; Abhinav Kumar (QUIC)
> ; Sankeerth Billakanti (QUIC)
> 
> Subject: Re: [PATCH v7 01/15] drm/msm/disp/dpu: clear dpu_assign_crtc and
> get crtc from connector state instead of dpu_enc
> 
> WARNING: This email originated from outside of Qualcomm. Please be wary
> of any links or attachments, and do not enable macros.
> 
> On 13/09/2022 20:04, Dmitry Baryshkov wrote:
> > On 13/09/2022 17:51, Vinod Polimera wrote:
> >> Update crtc retrieval from dpu_enc to dpu_enc connector state,
> >> since new links get set as part of the dpu enc virt mode set.
> >> The dpu_enc->crtc cache is no more needed, hence cleaning it as
> >> part of this change.
> >>
> >> Signed-off-by: Vinod Polimera 
> >> ---
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c|  4 
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 35
> >> -
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  8 ---
> >>   3 files changed, 14 insertions(+), 33 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >> index 13ce321..8ec9a13 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >> @@ -1029,7 +1029,6 @@ static void dpu_crtc_disable(struct drm_crtc
> *crtc,
> >>*/
> >>   if (dpu_encoder_get_intf_mode(encoder) == INTF_MODE_VIDEO)
> >>   release_bandwidth = true;
> >> -dpu_encoder_assign_crtc(encoder, NULL);
> >>   }
> >>   /* wait for frame_event_done completion */
> >> @@ -1099,9 +1098,6 @@ static void dpu_crtc_enable(struct drm_crtc
> *crtc,
> >>   trace_dpu_crtc_enable(DRMID(crtc), true, dpu_crtc);
> >>   dpu_crtc->enabled = true;
> >> -drm_for_each_encoder_mask(encoder, crtc->dev,
> >> crtc->state->encoder_mask)
> >> -dpu_encoder_assign_crtc(encoder, crtc);
> >> -
> >>   /* Enable/restore vblank irq handling */
> >>   drm_crtc_vblank_on(crtc);
> >>   }
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> index 9c6817b..0c7d8b5 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> @@ -132,11 +132,6 @@ enum dpu_enc_rc_states {
> >>* @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
> >> - * @crtc:Pointer to the currently assigned crtc. Normally you
> >> - *would use crtc->state->encoder_mask to determine the
> >> - *link between encoder/crtc. However in this case we need
> >> - *to track crtc in the disable() hook which is called
> >> - *_after_ encoder_mask is cleared.
> >>* @connector:If a mode is set, cached pointer to the active
> >> connector
> >>* @crtc_kickoff_cb:Callback into CRTC that will flush & start
> >>*all CTL paths
> >> @@ -181,7 +176,6 @@ struct dpu_encoder_virt {
> >>   bool intfs_swapped;
> >> -struct drm_crtc *crtc;
> >>   struct drm_connector *connector;
> >>   struct dentry *debugfs_root;
> >> @@ -1288,6 +1282,7 @@ static void dpu_encoder_vblank_callback(struct
> >> drm_encoder *drm_enc,
> >>   struct dpu_encoder_phys *phy_enc)
> >>   {
> >>   struct dpu_encoder_virt *dpu_enc = NULL;
> >> +struct drm_crtc *crtc;
> >>   unsigned long lock_flags;
> >>   if (!drm_enc || !phy_enc)
> >> @@ -1298,9 +1293,14 @@ static void
> dpu_encoder_vblank_callback(struct
> >> drm_encoder *drm_enc,
> >>   atomic_inc(_enc->vsync_cnt);
> >> +if (!dpu_enc->connector || !dpu_enc->connector->state)
> >> +return;
> >> +
> >> +crtc = dpu_enc->connector->state->crtc;
> >> +
> >>   spin_lock_irqsave(_enc->enc_spinlock, lock_flags);
> >> -if (dpu_enc->crtc)
> >> -dpu_crtc_vblank_callback(dpu_enc->crtc);
> >> +if (crtc)
> >> +dpu_crtc_vblank_callback(crtc);
> >>   spin_unlock_irqrestore(_enc->enc_spinlock, lock_flags);
> >
> > Stephen's comment about reading the state from outside of the lock and
> > then using local variable under spinlock is still valid. Moreover I'm
> > not sure that enc_spinlock protects connector's state. I'd say one has
> > to take the modesetting lock here.
> 
> s/Stephen's/Doug's/
As this is in 

[Bug 213145] AMDGPU resets, timesout and crashes after "*ERROR* Waiting for fences timed out!"

2022-10-12 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=213145

Paul Menzel (pmenzel+bugzilla.kernel@molgen.mpg.de) changed:

   What|Removed |Added

 CC||pmenzel+bugzilla.kernel.org
   ||@molgen.mpg.de

--- Comment #26 from Paul Menzel (pmenzel+bugzilla.kernel@molgen.mpg.de) ---
(In reply to Tomas Gayoso from comment #9)

[…]

> Recompiling Mesa 21.1.2 with the attached patch fixes the issue for me in
> kernels  5.10.42 and 5.12.9.

As the original report is not a Linux kernel but a Mesa issue, can you please
close this issue.

All other commenters, if you still experiencing this issue with the latest
Linux kernel and Mesa version, please create a new issue at the Mesa issue
tracker or here, if it’s a Linux kernel issue.

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are watching the assignee of the bug.

Re: [PATCH v4 5/5] drm/ofdrm: Support big-endian scanout buffers

2022-10-12 Thread Thomas Zimmermann

Hi

Am 12.10.22 um 10:38 schrieb Arnd Bergmann:

On Wed, Oct 12, 2022, at 10:27 AM, Thomas Zimmermann wrote:

Am 12.10.22 um 09:44 schrieb Arnd Bergmann:

On Wed, Oct 12, 2022, at 9:40 AM, Thomas Zimmermann wrote:

Am 12.10.22 um 09:17 schrieb Arnd Bergmann:

On Wed, Oct 12, 2022, at 8:46 AM, Thomas Zimmermann wrote:



Does qemu mark the device has having a particular endianess then, or
does it switch the layout of the framebuffer to match what the CPU
does?


The latter. On neither architecture does qemu expose this flag. The
default endianess corresponds to the host.


"host" as in the machine that qemu runs on, or the machine that is
being emulated? I suppose it would be broken either way, but in the
latter case, we could get away with detecting that the machine is
running under qemu.


Sorry, my mistake. I meant "guest": the endianess of the framebuffer
corresponds to the endianess of the emulated machine.  Given that many
graphics cards support LE and BE modes, I assume that this behavior
mimics real-hardware systems.


Not really: While the hardware may be able to switch between
the modes, something has to actively set some hardware registers up
that way, but the offb/ofdrm driver has no interface for interacting
with that register, and the bootloader or firmware code that knows
about the register has no information about what kernel it will
eventually run. This is a bit architecture dependent, as e.g. on
MIPS, a bi-endian hardware platform has to run a bootloader with the
same endianness as the kernel, but on arm and powerpc the bootloader
is usually fixed and the kernel switches to its configured endianness
in the first few instructions after it gets entered.


Could well be. But ofdrm intents to replace offb and this test has 
worked well in offb for almost 15 yrs. If there are bug reports, I'm 
happy to take patches, but until then I see no reason to change it.


Best regards
Thomas



  Arnd


--
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: [RFC PATCH v5 3/6] drm/tidss: Add support for AM625 DSS

2022-10-12 Thread Tomi Valkeinen

On 28/09/2022 20:52, Aradhya Bhatia wrote:

Add support for the DSS controller on TI's new AM625 SoC in the tidss
driver.

The first video port (VP0) in am625-dss can output OLDI signals through
2 OLDI TXes. A 3rd port has been added with "DISPC_VP_OLDI" bus type.

Signed-off-by: Aradhya Bhatia 
---
  drivers/gpu/drm/tidss/tidss_dispc.c | 61 -
  drivers/gpu/drm/tidss/tidss_dispc.h |  3 ++
  drivers/gpu/drm/tidss/tidss_drv.c   |  1 +
  3 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c 
b/drivers/gpu/drm/tidss/tidss_dispc.c
index dd3c6a606ae2..34f0da4bb3e3 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.c
+++ b/drivers/gpu/drm/tidss/tidss_dispc.c
@@ -93,6 +93,7 @@ const struct dispc_features dispc_k2g_feats = {
.common_regs = tidss_k2g_common_regs,
  
  	.num_vps = 1,

+   .num_max_ports = 1,


I would just use "num_ports" here, as it describes the HW (e.g. we have 
num_vps = 4 for J7, even if we'd only use one of the VPs).


I would also rename "TIDSS_MAX_PORTS". Maybe TIDSS_MAX_VPS. And check 
carefully that it's never used for the output ports.


Or maybe this field should be "num_output_ports", and try to use "output 
port" term in the driver for the..., well, output ports, to make the 
distinction between the videoport and output port more clear.


 Tomi



Re: [RFC PATCH v5 1/6] dt-bindings: display: ti, am65x-dss: Add am625 dss compatible

2022-10-12 Thread Tomi Valkeinen

On 28/09/2022 20:52, Aradhya Bhatia wrote:

Add ti,am625-dss compatible string.
The DSS IP on TI's AM625 SoC is an update from the DSS on TI's AM65X
SoC. The former has an additional OLDI TX to enable a 2K resolution on
OLDI displays or enable 2 duplicated displays with a smaller resolution.

Signed-off-by: Aradhya Bhatia 
Reviewed-by: Rahul T R 
Acked-by: Krzysztof Kozlowski 
---
  .../devicetree/bindings/display/ti/ti,am65x-dss.yaml  | 4 +++-
  1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml 
b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
index 5c7d2cbc4aac..6bbce921479d 100644
--- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
+++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
@@ -19,7 +19,9 @@ description: |
  
  properties:

compatible:
-const: ti,am65x-dss
+enum:
+  - ti,am625-dss
+  - ti,am65x-dss
  
reg:

  description:


I think you can squash this and the next one together.

 Tomi



Re: [RFC PATCH] drm/syncobj: add IOCTL to register an eventfd for a timeline

2022-10-12 Thread Christian König

Am 12.10.22 um 12:25 schrieb Simon Ser:

On Tuesday, October 11th, 2022 at 14:10, Christian König 
 wrote:


Am 10.10.22 um 11:13 schrieb Simon Ser:

On Sunday, October 9th, 2022 at 20:00, Christian König 
 wrote:


Am 09.10.22 um 16:40 schrieb Simon Ser:


Introduce a new DRM_IOCTL_SYNCOBJ_TIMELINE_REGISTER_EVENTFD IOCTL
which signals an eventfd when a timeline point completes.

I was entertaining the same though for quite a while, but I would even
go a step further and actually always base the wait before signal
functionality of the drm_syncobj and the eventfd functionality. That
would save us quite a bit of complexity I think.

Hm what do you mean exactly? I'm not sure I'm following.

Essentially we have the syncobj_wait_entry structure which is added to
the list whenever somebody starts to wait for a sequence which hasn't
materialized yet.

Instead of extending this maybe just completely nuke the
syncobj_wait_entry handling and replace it with your implementation here.

Hm, no sure I understand how that would work. We don't have an eventfd in the
WAIT IOCTL...

We could merge the two structs and figure out which callback to invoke based
on which fields are filled, but I figured two separate structs would be make
for a cleaner split.


In this case feel free to go ahead with this approach.

Just make sure that you always add the eventfd structure to the right 
list. For example the list_add in drm_syncobj_add_eventfd() doesn't seem 
to be correct of hand.


Regards,
Christian.


[Bug 213145] AMDGPU resets, timesout and crashes after "*ERROR* Waiting for fences timed out!"

2022-10-12 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=213145

--- Comment #25 from James Le Cuirot (ch...@gentoo.org) ---
I do, yes, under Wayland. I did a system update recently but if the problem
reoccurs, I'll try that next. Thanks!

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are watching the assignee of the bug.

Re: [PATCH v3 12/17] drm/i915/vm_bind: Implement I915_GEM_EXECBUFFER3 ioctl

2022-10-12 Thread Matthew Auld

On 10/10/2022 07:58, Niranjana Vishwanathapura wrote:

Implement new execbuf3 ioctl (I915_GEM_EXECBUFFER3) which only
works in vm_bind mode. The vm_bind mode only works with
this new execbuf3 ioctl.

The new execbuf3 ioctl will not have any list of objects to validate
bind as all required objects binding would have been requested by the
userspace before submitting the execbuf3.

Legacy features like relocations etc are not supported by execbuf3.

v2: Add more input validity checks.
v3: batch_address is a VA (not an array) if num_batches=1,
 minor cleanup

Signed-off-by: Niranjana Vishwanathapura 
Signed-off-by: Andi Shyti 
---
  drivers/gpu/drm/i915/Makefile |   1 +
  .../gpu/drm/i915/gem/i915_gem_execbuffer3.c   | 580 ++
  drivers/gpu/drm/i915/gem/i915_gem_ioctls.h|   2 +
  drivers/gpu/drm/i915/i915_driver.c|   1 +
  include/uapi/drm/i915_drm.h   |  61 ++
  5 files changed, 645 insertions(+)
  create mode 100644 drivers/gpu/drm/i915/gem/i915_gem_execbuffer3.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 3564307699ea..94520b79e7e7 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -150,6 +150,7 @@ gem-y += \
gem/i915_gem_domain.o \
gem/i915_gem_execbuffer_common.o \
gem/i915_gem_execbuffer.o \
+   gem/i915_gem_execbuffer3.o \
gem/i915_gem_internal.o \
gem/i915_gem_object.o \
gem/i915_gem_lmem.o \
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer3.c 
b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer3.c
new file mode 100644
index ..1f38f658066a
--- /dev/null
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer3.c
@@ -0,0 +1,580 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#include 
+#include 
+
+#include 
+
+#include "gt/intel_context.h"
+#include "gt/intel_gpu_commands.h"
+#include "gt/intel_gt.h"
+
+#include "i915_drv.h"
+#include "i915_gem_context.h"
+#include "i915_gem_execbuffer_common.h"
+#include "i915_gem_ioctls.h"
+#include "i915_gem_vm_bind.h"
+#include "i915_trace.h"
+
+#define __EXEC3_ENGINE_PINNED  BIT_ULL(32)
+#define __EXEC3_INTERNAL_FLAGS (~0ull << 32)
+
+/* Catch emission of unexpected errors for CI! */
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
+#undef EINVAL
+#define EINVAL ({ \
+   DRM_DEBUG_DRIVER("EINVAL at %s:%d\n", __func__, __LINE__); \
+   22; \
+})
+#endif
+
+/**
+ * DOC: User command execution with execbuf3 ioctl
+ *
+ * A VM in VM_BIND mode will not support older execbuf mode of binding.
+ * The execbuf ioctl handling in VM_BIND mode differs significantly from the
+ * older execbuf2 ioctl (See struct drm_i915_gem_execbuffer2).
+ * Hence, a new execbuf3 ioctl has been added to support VM_BIND mode. (See
+ * struct drm_i915_gem_execbuffer3). The execbuf3 ioctl will not accept any
+ * execlist. Hence, no support for implicit sync.
+ *
+ * The new execbuf3 ioctl only works in VM_BIND mode and the VM_BIND mode only
+ * works with execbuf3 ioctl for submission.
+ *
+ * The execbuf3 ioctl directly specifies the batch addresses instead of as
+ * object handles as in execbuf2 ioctl. The execbuf3 ioctl will also not
+ * support many of the older features like in/out/submit fences, fence array,
+ * default gem context etc. (See struct drm_i915_gem_execbuffer3).
+ *
+ * In VM_BIND mode, VA allocation is completely managed by the user instead of
+ * the i915 driver. Hence all VA assignment, eviction are not applicable in
+ * VM_BIND mode. Also, for determining object activeness, VM_BIND mode will not
+ * be using the i915_vma active reference tracking. It will instead check the
+ * dma-resv object's fence list for that.
+ *
+ * So, a lot of code supporting execbuf2 ioctl, like relocations, VA evictions,
+ * vma lookup table, implicit sync, vma active reference tracking etc., are not
+ * applicable for execbuf3 ioctl.


I guess EXEC_CAPTURE is also now gone? Is that expected? We ofc don't 
have the list of objects so perhaps doesn't make sense any more. Just 
double checking...


Re: [RFC PATCH] drm/syncobj: add IOCTL to register an eventfd for a timeline

2022-10-12 Thread Simon Ser
On Tuesday, October 11th, 2022 at 14:10, Christian König 
 wrote:

> Am 10.10.22 um 11:13 schrieb Simon Ser:
> > On Sunday, October 9th, 2022 at 20:00, Christian König 
> >  wrote:
> >
> >> Am 09.10.22 um 16:40 schrieb Simon Ser:
> >>
> >>> Introduce a new DRM_IOCTL_SYNCOBJ_TIMELINE_REGISTER_EVENTFD IOCTL
> >>> which signals an eventfd when a timeline point completes.
> >> I was entertaining the same though for quite a while, but I would even
> >> go a step further and actually always base the wait before signal
> >> functionality of the drm_syncobj and the eventfd functionality. That
> >> would save us quite a bit of complexity I think.
> > Hm what do you mean exactly? I'm not sure I'm following.
> 
> Essentially we have the syncobj_wait_entry structure which is added to
> the list whenever somebody starts to wait for a sequence which hasn't
> materialized yet.
> 
> Instead of extending this maybe just completely nuke the
> syncobj_wait_entry handling and replace it with your implementation here.

Hm, no sure I understand how that would work. We don't have an eventfd in the
WAIT IOCTL...

We could merge the two structs and figure out which callback to invoke based
on which fields are filled, but I figured two separate structs would be make
for a cleaner split.


Re: [PATCH 0/3] Add _PICK_EVEN_RANGES

2022-10-12 Thread Jani Nikula
On Tue, 11 Oct 2022, Lucas De Marchi  wrote:
> Add a new macro, _PICK_EVEN_RANGES, that supports using 2 address
> ranges. This should cover most of our needs for _MMIO_PLL3 and such.
> To show what is achieved with the new macro, convert some PLL-related
> macros to use it instead of _MMIO_PLL3.

While there's nothing particularly wrong about the solution when looked
at in isolation, I do have pretty strong reservations on the whole.

We have:

1) _PICK_EVEN() used in _PIPE() and friends

2) _PICK() used in _MMIO_PIPE3() and friends

3) ->pipe_offsets[] etc. adjustment used in _MMIO_PIPE2() and friends

4) ->ddi_index[] mapping proposed in [1]

5) _PICK_EVEN_RANGES() proposed here

Originally we only had the first one, when the hardware was
simpler. Every single addition since then made sense at the time, but if
we add 4 & 5 to the mix, I think it's just too many options.

I think it's time to take a step back and figure out if there's a more
generic approach that could be used.


BR,
Jani.


[1] https://patchwork.freedesktop.org/series/108833/

-- 
Jani Nikula, Intel Open Source Graphics Center


Re: [PATCH v4 5/5] drm/ofdrm: Support big-endian scanout buffers

2022-10-12 Thread Arnd Bergmann
On Wed, Oct 12, 2022, at 10:27 AM, Thomas Zimmermann wrote:
> Am 12.10.22 um 09:44 schrieb Arnd Bergmann:
>> On Wed, Oct 12, 2022, at 9:40 AM, Thomas Zimmermann wrote:
>>> Am 12.10.22 um 09:17 schrieb Arnd Bergmann:
 On Wed, Oct 12, 2022, at 8:46 AM, Thomas Zimmermann wrote:
>>>
 Does qemu mark the device has having a particular endianess then, or
 does it switch the layout of the framebuffer to match what the CPU
 does?
>>>
>>> The latter. On neither architecture does qemu expose this flag. The
>>> default endianess corresponds to the host.
>> 
>> "host" as in the machine that qemu runs on, or the machine that is
>> being emulated? I suppose it would be broken either way, but in the
>> latter case, we could get away with detecting that the machine is
>> running under qemu.
>
> Sorry, my mistake. I meant "guest": the endianess of the framebuffer 
> corresponds to the endianess of the emulated machine.  Given that many 
> graphics cards support LE and BE modes, I assume that this behavior 
> mimics real-hardware systems.

Not really: While the hardware may be able to switch between
the modes, something has to actively set some hardware registers up
that way, but the offb/ofdrm driver has no interface for interacting
with that register, and the bootloader or firmware code that knows
about the register has no information about what kernel it will
eventually run. This is a bit architecture dependent, as e.g. on
MIPS, a bi-endian hardware platform has to run a bootloader with the
same endianness as the kernel, but on arm and powerpc the bootloader
is usually fixed and the kernel switches to its configured endianness
in the first few instructions after it gets entered.

 Arnd


Re: pr-tracker-bot for drm subsystem?

2022-10-12 Thread Jani Nikula


Ping?

On Thu, 15 Sep 2022, Jani Nikula  wrote:
> Hey all, I'd be interested in having the pr-tracker-bot [1] set up for
> the drm subsystem, following the dri-devel mailing list [2] and
> notifying when the pull requests have been merged to either the drm-next
> or drm-fixes branches of the main drm repository [3].
>
> What would this require in terms of the tracker bot code?
>
> Is the idea that the service could be expanded to cover subsystems
> instead of just LKML and mainline, or would all subsystems have to set
> it up for themselves with their own cron jobs on their own servers?
>
> Other considerations?
>
>
> BR,
> Jani.
>
>
> [1] https://korg.docs.kernel.org/prtracker.html
> [2] https://lists.freedesktop.org/mailman/listinfo/dri-devel
> [3] https://cgit.freedesktop.org/drm/drm/

-- 
Jani Nikula, Intel Open Source Graphics Center


Re: [PATCH v4 5/5] drm/ofdrm: Support big-endian scanout buffers

2022-10-12 Thread Thomas Zimmermann

Hi

Am 12.10.22 um 09:44 schrieb Arnd Bergmann:

On Wed, Oct 12, 2022, at 9:40 AM, Thomas Zimmermann wrote:

Am 12.10.22 um 09:17 schrieb Arnd Bergmann:

On Wed, Oct 12, 2022, at 8:46 AM, Thomas Zimmermann wrote:



Does qemu mark the device has having a particular endianess then, or
does it switch the layout of the framebuffer to match what the CPU
does?


The latter. On neither architecture does qemu expose this flag. The
default endianess corresponds to the host.


"host" as in the machine that qemu runs on, or the machine that is
being emulated? I suppose it would be broken either way, but in the
latter case, we could get away with detecting that the machine is
running under qemu.


Sorry, my mistake. I meant "guest": the endianess of the framebuffer 
corresponds to the endianess of the emulated machine.  Given that many 
graphics cards support LE and BE modes, I assume that this behavior 
mimics real-hardware systems.


Best regards
Thomas



 Arnd


--
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] drm/edid/firmware: stop using throwaway platform device

2022-10-12 Thread Jani Nikula
On Tue, 11 Oct 2022, Matthieu CHARETTE  wrote:
> Currently the EDID is requested during the resume. But since it's
> requested too early, this means before the filesystem is mounted, the
> firmware request fails. This make the DRM driver crash when resuming.
> This kind of issue should be prevented by the firmware caching process
> which cache every firmware requested for the next resume. But since we
> are using a temporary device, the firmware isn't cached on suspend
> since the device doesn't work anymore.
> When using a non temporary device to get the EDID, the firmware will
> be cached on suspend for the next resume. So requesting the firmware
> during resume will succeed.
> But if the firmware has never been requested since the boot, this
> means that the monitor isn't plugged since the boot. The kernel will
> not be caching the EDID. So if we plug the monitor while the machine
> is suspended. The resume will fail to load the firmware. And the DRM
> driver will crash.
> So basically, your fix should solve the issue except for the case
> where the monitor hasn't been plugged since boot and is plugged while
> the machine is suspended.
> I hope I was clear. Tell me if I wasn't. I'm not really good at explaining.

That was a pretty good explanation. The only thing I'm missing is what
the failure mode is exactly when you claim the driver will crash. Why
would request_firmware() "crash" if called for the first time on the
resume path?

I'm not sure I care much about not being able to load the firmware EDID
in the suspend-plug-resume case (as this can be remedied with a
subsequent modeset), but obviously any errors need to be handled
gracefully, without crashing.

BR,
Jani.


-- 
Jani Nikula, Intel Open Source Graphics Center


Re: [RESEND PATCH v2] drm/mediatek: Add AFBC support to Mediatek DRM driver

2022-10-12 Thread AngeloGioacchino Del Regno

Il 11/10/22 20:28, Justin Green ha scritto:

Hi Angelo,
Thanks for the suggestions! I'll upload another patch with those changes.

Re the pitch register math, would it be acceptable to define separate
macros for the LSB and MSB to abstract away the magic numbers? For
example:
#define OVL_PITCH_MSB(n)((n >> 16) & GENMASK(15, 0))
#define OVL_PITCH_LSB(n)(n & GENMASK(15, 0))



These would be different from the macros that are available in bitfield.h, but
not *fundamentally* different, so these would look a little redundant...

I think that you refer to that `pitch` variable that's coming from the DRM(/fb)
API... and bitfield macros are for register access... so I guess that one clean
way of avoiding the magic shifting (that is purely used to split the 32-bits
number in two 16-bits 'chunks') would be to perhaps use a union, so that you
will have something like u.pitch_lsb, u.pitch_msb (with lsb/msb being two u16).

That'd better represent what is going on here, I believe?

Regards,
Angelo


Regards,
Justin

On Tue, Oct 11, 2022 at 5:09 AM AngeloGioacchino Del Regno
 wrote:


Il 10/10/22 17:01, Justin Green ha scritto:

From: Justin Green 

Add AFBC support to Mediatek DRM driver and enable on MT8195.

Tested on MT8195 and confirmed both correct video output and improved DRAM
bandwidth performance.

v2:
Marked mtk_ovl_set_afbc as static, reflowed some lines to fit column
limit.

Signed-off-by: Justin Green 


Hello Justin,
thanks for the patch!

However, there's something to improve...


---
   drivers/gpu/drm/mediatek/mtk_disp_ovl.c  | 108 ---
   drivers/gpu/drm/mediatek/mtk_drm_plane.c |  37 +++-
   drivers/gpu/drm/mediatek/mtk_drm_plane.h |   8 ++
   3 files changed, 140 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c 
b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 002b0f6cae1a..1724ea85a840 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c


..snip..


@@ -208,6 +231,8 @@ int mtk_ovl_layer_check(struct device *dev, unsigned int 
idx,
   {
   struct drm_plane_state *state = _state->base;
   unsigned int rotation = 0;
+ unsigned long long modifier;
+ unsigned int fourcc;

   rotation = drm_rotation_simplify(state->rotation,
DRM_MODE_ROTATE_0 |
@@ -226,6 +251,30 @@ int mtk_ovl_layer_check(struct device *dev, unsigned int 
idx,
   if (state->fb->format->is_yuv && rotation != 0)
   return -EINVAL;

+ if (state->fb->modifier) {
+ struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);


Since you're introducing modifier and fourcc for this branch only, you
may as well just declare them here instead, but either way is fine.


+
+ if (!ovl->data->supports_afbc)
+ return -EINVAL;
+
+ modifier = state->fb->modifier;
+
+ if (modifier != 
DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
+ AFBC_FORMAT_MOD_SPLIT |
+ AFBC_FORMAT_MOD_SPARSE))
+ return -EINVAL;
+
+ fourcc = state->fb->format->format;
+ if (fourcc != DRM_FORMAT_BGRA &&
+ fourcc != DRM_FORMAT_ABGR &&
+ fourcc != DRM_FORMAT_ARGB &&
+ fourcc != DRM_FORMAT_XRGB &&
+ fourcc != DRM_FORMAT_XBGR &&
+ fourcc != DRM_FORMAT_RGB888 &&
+ fourcc != DRM_FORMAT_BGR888)
+ return -EINVAL;
+ }
+
   state->rotation = rotation;

   return 0;
@@ -310,11 +359,14 @@ void mtk_ovl_layer_config(struct device *dev, unsigned 
int idx,
   struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
   struct mtk_plane_pending_state *pending = >pending;
   unsigned int addr = pending->addr;
- unsigned int pitch = pending->pitch & 0x;
+ unsigned int hdr_addr = pending->hdr_addr;
+ unsigned int pitch = pending->pitch;
+ unsigned int hdr_pitch = pending->hdr_pitch;
   unsigned int fmt = pending->format;
   unsigned int offset = (pending->y << 16) | pending->x;
   unsigned int src_size = (pending->height << 16) | pending->width;
   unsigned int con;
+ bool is_afbc = pending->modifier;

   if (!pending->enable) {
   mtk_ovl_layer_off(dev, idx, cmdq_pkt);
@@ -335,16 +387,39 @@ void mtk_ovl_layer_config(struct device *dev, unsigned 
int idx,
   addr += pending->pitch - 1;
   }

- mtk_ddp_write_relaxed(cmdq_pkt, con, >cmdq_reg, ovl->regs,
-   DISP_REG_OVL_CON(idx));
- mtk_ddp_write_relaxed(cmdq_pkt, pitch, >cmdq_reg, ovl->regs,
-   DISP_REG_OVL_PITCH(idx));
- mtk_ddp_write_relaxed(cmdq_pkt, src_size, >cmdq_reg, ovl->regs,
-   

Re: [PATCH] drm: mediatek: Modify dpi power on/off sequence.

2022-10-12 Thread xinlei . lee
On Mon, 2022-09-05 at 21:53 +0800, xinlei@mediatek.com wrote:
> From: Xinlei Lee 
> 
> Modify dpi power on/off sequence so that the first gpio operation
> will take effect.
> 
> Fixes: 6bd4763fd532 ("drm/mediatek: set dpi pin mode to gpio low to
> avoid leakage
> current")
> 
> Signed-off-by: Xinlei Lee 
> 
> ---
> Base on the branch of Linux-next/master.
> Because dpi power_on/off is protected by dpi->refcount, the first
> time
> it cannot be powered on and off successfully, it will cause leakage.
> ---
> ---
>  drivers/gpu/drm/mediatek/mtk_dpi.c | 12 ++--
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c
> b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 630a4e301ef6..2ce1a39ce3bf 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -462,9 +462,6 @@ static void mtk_dpi_power_off(struct mtk_dpi
> *dpi)
>   if (--dpi->refcount != 0)
>   return;
>  
> - if (dpi->pinctrl && dpi->pins_gpio)
> - pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
> -
>   mtk_dpi_disable(dpi);
>   clk_disable_unprepare(dpi->pixel_clk);
>   clk_disable_unprepare(dpi->engine_clk);
> @@ -489,9 +486,6 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi)
>   goto err_pixel;
>   }
>  
> - if (dpi->pinctrl && dpi->pins_dpi)
> - pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi);
> -
>   return 0;
>  
>  err_pixel:
> @@ -721,6 +715,9 @@ static void mtk_dpi_bridge_disable(struct
> drm_bridge *bridge)
>  {
>   struct mtk_dpi *dpi = bridge_to_dpi(bridge);
>  
> + if (dpi->pinctrl && dpi->pins_gpio)
> + pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
> +
>   mtk_dpi_power_off(dpi);
>  }
>  
> @@ -728,6 +725,9 @@ static void mtk_dpi_bridge_enable(struct
> drm_bridge *bridge)
>  {
>   struct mtk_dpi *dpi = bridge_to_dpi(bridge);
>  
> + if (dpi->pinctrl && dpi->pins_dpi)
> + pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi);
> +
>   mtk_dpi_power_on(dpi);
>   mtk_dpi_set_display_mode(dpi, >mode);
>   mtk_dpi_enable(dpi);

Hi CK,

Gentle ping for this patch, if there is anything I need to modify,
please kindly let me know.

Best Regards!
xinlei



Re: [PATCH v4 5/5] drm/ofdrm: Support big-endian scanout buffers

2022-10-12 Thread Arnd Bergmann
On Wed, Oct 12, 2022, at 9:40 AM, Thomas Zimmermann wrote:
> Am 12.10.22 um 09:17 schrieb Arnd Bergmann:
>> On Wed, Oct 12, 2022, at 8:46 AM, Thomas Zimmermann wrote:
>
>> Does qemu mark the device has having a particular endianess then, or
>> does it switch the layout of the framebuffer to match what the CPU
>> does?
>
> The latter. On neither architecture does qemu expose this flag. The 
> default endianess corresponds to the host.

"host" as in the machine that qemu runs on, or the machine that is
being emulated? I suppose it would be broken either way, but in the
latter case, we could get away with detecting that the machine is
running under qemu.

Arnd


Re: [PATCH v4 5/5] drm/ofdrm: Support big-endian scanout buffers

2022-10-12 Thread Thomas Zimmermann

Hi

Am 12.10.22 um 09:17 schrieb Arnd Bergmann:

On Wed, Oct 12, 2022, at 8:46 AM, Thomas Zimmermann wrote:

Am 11.10.22 um 22:06 schrieb Arnd Bergmann:

On Tue, Oct 11, 2022, at 1:30 PM, Thomas Zimmermann wrote:

Am 11.10.22 um 09:46 schrieb Javier Martinez Canillas:

+static bool display_get_big_endian_of(struct drm_device *dev, struct 
device_node *of_node)
+{
+   bool big_endian;
+
+#ifdef __BIG_ENDIAN
+   big_endian = true;
+   if (of_get_property(of_node, "little-endian", NULL))
+   big_endian = false;
+#else
+   big_endian = false;
+   if (of_get_property(of_node, "big-endian", NULL))
+   big_endian = true;
+#endif
+
+   return big_endian;
+}
+


Ah, I see. The heuristic then is whether the build is BE or LE or if the Device
Tree has an explicit node defining the endianess. The patch looks good to me:


Yes. I took this test from offb.


Has the driver been tested with little-endian kernels though? While
ppc32 kernels are always BE, you can build kernels as either big-endian
or little-endian for most (modern) powerpc64 and arm/arm64 hardware,
and I don't see why that should change the defaults of the driver
when describing the same framebuffer hardware.


Yes, I tested this on qemu's ppc64le and ppc64.


Does qemu mark the device has having a particular endianess then, or
does it switch the layout of the framebuffer to match what the CPU
does?


The latter. On neither architecture does qemu expose this flag. The 
default endianess corresponds to the host.


Best regards
Thomas



I've seen other cases where devices in qemu were defined using an
arbitrary definition of "cpu-endian", which is generally not how
real hardware works.

 Arnd


--
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


[PATCH -next] drm/amdgpu/si_dma: remove unused variable in si_dma_stop()

2022-10-12 Thread Yang Yingliang
After commit 571c05365892 ("drm/amdgpu: switch sdma buffer function
tear down to a helper"), the variable 'ring' is not used anymore, it
can be removed.

Signed-off-by: Yang Yingliang 
---
 drivers/gpu/drm/amd/amdgpu/si_dma.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c 
b/drivers/gpu/drm/amd/amdgpu/si_dma.c
index 4d5e718540aa..abca8b529721 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_dma.c
+++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c
@@ -112,14 +112,12 @@ static void si_dma_ring_emit_fence(struct amdgpu_ring 
*ring, u64 addr, u64 seq,
 
 static void si_dma_stop(struct amdgpu_device *adev)
 {
-   struct amdgpu_ring *ring;
u32 rb_cntl;
unsigned i;
 
amdgpu_sdma_unset_buffer_funcs_helper(adev);
 
for (i = 0; i < adev->sdma.num_instances; i++) {
-   ring = >sdma.instance[i].ring;
/* dma0 */
rb_cntl = RREG32(DMA_RB_CNTL + sdma_offsets[i]);
rb_cntl &= ~DMA_RB_ENABLE;
-- 
2.25.1



Re: [PATCH v2 1/4] drm/mgag200: Do not call drm_atomic_add_affected_planes()

2022-10-12 Thread Thomas Zimmermann



Am 11.10.22 um 18:51 schrieb Javier Martinez Canillas:

There's no need to add planes to the atomic state. Remove the call
to drm_atomic_add_affected_planes() from mgag200.

On full modesets, the DRM helpers already add a CRTC's planes to the
atomic state; see drm_atomic_helper_check_modeset(). There's no reason
to call drm_atomic_add_affected_planes() unconditionally in the CRTC's
atomic_check() in mgag200. It's also too late, as the atomic_check()
of the added planes will not be called before the commit.

Suggested-by: Thomas Zimmermann 
Signed-off-by: Javier Martinez Canillas 


Reviewed-by: Thomas Zimmermann 


---

(no changes since v1)

  drivers/gpu/drm/mgag200/mgag200_mode.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c 
b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 5f7eb642f0c6..758629da95d9 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -601,7 +601,7 @@ int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, 
struct drm_atomic_st
}
}
  
-	return drm_atomic_add_affected_planes(new_state, crtc);

+   return 0;
  }
  
  void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *old_state)


--
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: Render only DRM devices

2022-10-12 Thread Simon Ser
On Wednesday, October 12th, 2022 at 08:18, Christian König 
 wrote:

> DRM auth based authentication is seen as a security risk and we want to
> get rid of that for render only devices (at least for the new ones).

Right, that makes sense for new hw/drivers. So we really need this to
be opt-in, we can't just do it for all existing render-only drivers
without breaking the kernel no-regression rule.

> I should probably add a wider explanation to the commit message.

Good idea!


RE: [PATCH v6 04/10] drm/msm/dp: Add basic PSR support for eDP

2022-10-12 Thread Sankeerth Billakanti
Hi Doug,
I incorporated the comments in v7.

>Hi,
>
>On Mon, Jul 11, 2022 at 5:57 AM Vinod Polimera
> wrote:
>>
>> @@ -359,6 +367,24 @@ void dp_catalog_ctrl_lane_mapping(struct
>dp_catalog *dp_catalog)
>> ln_mapping);
>>  }
>>
>> +void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog,
>> +   bool enable) {
>> +   u32 val;
>> +   struct dp_catalog_private *catalog = container_of(dp_catalog,
>> +   struct dp_catalog_private,
>> +dp_catalog);
>> +
>> +   val = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
>> +   val &= ~DP_MAINLINK_CTRL_ENABLE;
>
>nit: the line above is useless. Remove. In the case that you're enabling you're
>just adding the bit back in. In the case that you're disabling you're doing the
>exact same operation below.
>

Incorporated the changes in v7

>
>> @@ -610,6 +636,47 @@ void dp_catalog_ctrl_hpd_config(struct dp_catalog
>*dp_catalog)
>> dp_write_aux(catalog, REG_DP_DP_HPD_CTRL,
>> DP_DP_HPD_CTRL_HPD_EN);  }
>>
>> +static void dp_catalog_enable_sdp(struct dp_catalog_private *catalog)
>> +{
>> +   /* trigger sdp */
>> +   dp_write_link(catalog, MMSS_DP_SDP_CFG3, UPDATE_SDP);
>> +   dp_write_link(catalog, MMSS_DP_SDP_CFG3, !UPDATE_SDP);
>
>!UPDATE_SDP is a really counter-intuitive way to say 0x0.
>

Changed to 0x0 in v7

>
>> @@ -645,6 +712,20 @@ u32 dp_catalog_hpd_get_intr_status(struct
>dp_catalog *dp_catalog)
>> return isr & (mask | ~DP_DP_HPD_INT_MASK);  }
>>
>> +int dp_catalog_ctrl_read_psr_interrupt_status(struct dp_catalog
>> +*dp_catalog)
>
>Why is the return type "int" and not "u32". It's a hardware register.
>It's u32 here. The caller assigns it to a u32.
>

Changed to u32

>
>> +void dp_ctrl_set_psr(struct dp_ctrl *dp_ctrl, bool enter) {
>> +   struct dp_ctrl_private *ctrl = container_of(dp_ctrl,
>> +   struct dp_ctrl_private, dp_ctrl);
>> +
>> +   if (!ctrl->panel->psr_cap.version)
>> +   return;
>> +
>> +   /*
>> +* When entering PSR,
>> +* 1. Send PSR enter SDP and wait for the PSR_UPDATE_INT
>> +* 2. Turn off video
>> +* 3. Disable the mainlink
>> +*
>> +* When exiting PSR,
>> +* 1. Enable the mainlink
>> +* 2. Send the PSR exit SDP
>> +*/
>> +   if (enter) {
>> +   reinit_completion(>psr_op_comp);
>> +   dp_catalog_ctrl_set_psr(ctrl->catalog, true);
>> +
>> +   if (!wait_for_completion_timeout(>psr_op_comp,
>> +   PSR_OPERATION_COMPLETION_TIMEOUT_JIFFIES)) {
>> +   DRM_ERROR("PSR_ENTRY timedout\n");
>> +   dp_catalog_ctrl_set_psr(ctrl->catalog, false);
>> +   return;
>> +   }
>> +
>> +   dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
>> +
>> +   dp_catalog_ctrl_psr_mainlink_enable(ctrl->catalog, false);
>> +   } else {
>> +   dp_catalog_ctrl_psr_mainlink_enable(ctrl->catalog,
>> + true);
>> +
>> +   dp_catalog_ctrl_set_psr(ctrl->catalog, false);
>
>My PSR knowledge is not very strong, but I do remember a recent commit
>from Brian Norris fly by for the Analogix controller. See commit
>c4c6ef229593 ("drm/bridge: analogix_dp: Make PSR-exit block less").
>
>In that commit it sounds as if we need to wait for _something_ (resync I
>guess?) here and not just return instantly.
>

In our case, the HW abstracts the necessary settings for regular psr exit.
However, we discovered some corner cases related to display off/suspend while 
sink is in psr,
I am incorporating a step to enable video and wait for video ready in v7.

>
>> @@ -388,6 +388,8 @@ static int dp_display_process_hpd_high(struct
>> dp_display_private *dp)
>>
>> edid = dp->panel->edid;
>>
>> +   dp->dp_display.psr_supported = !!dp->panel->psr_cap.version;
>> +
>
>nit: remove the "!!". You're already storing this in a "bool" which will handle
>this for you.
>
 
Made this change in v7.

>
>> +static const struct drm_bridge_funcs edp_bridge_ops = {
>> +   .atomic_enable = edp_bridge_atomic_enable,
>> +   .atomic_disable = edp_bridge_atomic_disable,
>> +   .atomic_post_disable = edp_bridge_atomic_post_disable,
>> +   .mode_set = dp_bridge_mode_set,
>> +   .mode_valid = dp_bridge_mode_valid,
>> +   .atomic_reset = drm_atomic_helper_bridge_reset,
>> +   .atomic_duplicate_state =
>drm_atomic_helper_bridge_duplicate_state,
>> +   .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
>> +   .atomic_check = edp_bridge_atomic_check, };
>
>nit: the location of your new functions is a little weird. You've got:
>
>1. DP functions
>2. eDP functions
>3. eDP structure
>4. DP structure
>
>I'd expect:
>
>1. DP functions
>2. DP structure
>3. eDP functions
>4. eDP structure
>

Changed the order in v7

>-Doug


Re: [PATCH v4 5/5] drm/ofdrm: Support big-endian scanout buffers

2022-10-12 Thread Arnd Bergmann
On Wed, Oct 12, 2022, at 8:46 AM, Thomas Zimmermann wrote:
> Am 11.10.22 um 22:06 schrieb Arnd Bergmann:
>> On Tue, Oct 11, 2022, at 1:30 PM, Thomas Zimmermann wrote:
>>> Am 11.10.22 um 09:46 schrieb Javier Martinez Canillas:
> +static bool display_get_big_endian_of(struct drm_device *dev, struct 
> device_node *of_node)
> +{
> + bool big_endian;
> +
> +#ifdef __BIG_ENDIAN
> + big_endian = true;
> + if (of_get_property(of_node, "little-endian", NULL))
> + big_endian = false;
> +#else
> + big_endian = false;
> + if (of_get_property(of_node, "big-endian", NULL))
> + big_endian = true;
> +#endif
> +
> + return big_endian;
> +}
> +

 Ah, I see. The heuristic then is whether the build is BE or LE or if the 
 Device
 Tree has an explicit node defining the endianess. The patch looks good to 
 me:
>>>
>>> Yes. I took this test from offb.
>> 
>> Has the driver been tested with little-endian kernels though? While
>> ppc32 kernels are always BE, you can build kernels as either big-endian
>> or little-endian for most (modern) powerpc64 and arm/arm64 hardware,
>> and I don't see why that should change the defaults of the driver
>> when describing the same framebuffer hardware.
>
> Yes, I tested this on qemu's ppc64le and ppc64.

Does qemu mark the device has having a particular endianess then, or
does it switch the layout of the framebuffer to match what the CPU
does?

I've seen other cases where devices in qemu were defined using an
arbitrary definition of "cpu-endian", which is generally not how
real hardware works.

Arnd


Re: [PATCH v4 5/5] drm/ofdrm: Support big-endian scanout buffers

2022-10-12 Thread Thomas Zimmermann

Hi

Am 11.10.22 um 22:06 schrieb Arnd Bergmann:

On Tue, Oct 11, 2022, at 1:30 PM, Thomas Zimmermann wrote:

Am 11.10.22 um 09:46 schrieb Javier Martinez Canillas:

+static bool display_get_big_endian_of(struct drm_device *dev, struct 
device_node *of_node)
+{
+   bool big_endian;
+
+#ifdef __BIG_ENDIAN
+   big_endian = true;
+   if (of_get_property(of_node, "little-endian", NULL))
+   big_endian = false;
+#else
+   big_endian = false;
+   if (of_get_property(of_node, "big-endian", NULL))
+   big_endian = true;
+#endif
+
+   return big_endian;
+}
+


Ah, I see. The heuristic then is whether the build is BE or LE or if the Device
Tree has an explicit node defining the endianess. The patch looks good to me:


Yes. I took this test from offb.


Has the driver been tested with little-endian kernels though? While
ppc32 kernels are always BE, you can build kernels as either big-endian
or little-endian for most (modern) powerpc64 and arm/arm64 hardware,
and I don't see why that should change the defaults of the driver
when describing the same framebuffer hardware.


Yes, I tested this on qemu's ppc64le and ppc64.

Best regards
Thomas



I could understand having a default to e.g. big-endian on all powerpc and
a default for little-endian on all arm, but having it tied to the
way the kernel is built seems wrong, and doesn't make sense in a
DT binding either.

   Arnd


--
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: Render only DRM devices

2022-10-12 Thread Christian König

Am 11.10.22 um 17:20 schrieb Simon Ser:

On Tuesday, October 11th, 2022 at 13:56, Christian König 
 wrote:


Am 11.10.22 um 13:37 schrieb Simon Ser:


On Tuesday, October 11th, 2022 at 13:04, Christian König 
ckoenig.leichtzumer...@gmail.com wrote:


we already have quite a bunch of devices which are essentially render
only and don't expose any connectors or more general display functionality.

Just recently I ran into a case where an older X/DDX combination
caused problems for such a device so I looked a bit into the
possibility to allow drivers to disable the primary node and only
expose the render node.

It turned out that this effectively hides the device from X, but
OpenGL and Vulkan can still use it perfectly fine.

The only crux is that this is checked so early in the initialization
that drivers don't have an opportunity to update their
dev->driver_features. So we will always need a separate drm_driver
structure for render only devices.
Typically render-only devices still expose a primary node, but don't
expose any KMS resources on it. See drmIsKMS() in libdrm.

Primary nodes could still be used by older user-space for rendering with
legacy DRM authentication.

Yeah, and that's exactly what we try to avoid :)

But, wouldn't that regress user-space which renders using primary nodes +
DRM auth?


Yes and that is completely intentional as well. At least for new 
hardware generations we shouldn't have any userspace using this any more.


DRM auth based authentication is seen as a security risk and we want to 
get rid of that for render only devices (at least for the new ones).


I should probably add a wider explanation to the commit message.

Thanks,
Christian.


  1   2   >