Re: [PATCH] MAINTAINERS: Update drm.git URL

2024-02-26 Thread Maxime Ripard
On Mon, Feb 26, 2024 at 04:21:23PM +0100, Maxime Ripard wrote:
> Now that the main DRM tree has moved to Gitlab, adjust the MAINTAINERS
> git trees to reflect the location change.
> 
> Signed-off-by: Maxime Ripard 

Applied to drm-next

Maxime


signature.asc
Description: PGP signature


Re: [rerere PATCH] nightly.conf: Switch drm.git to gitlab

2024-02-26 Thread Maxime Ripard
On Mon, Feb 26, 2024 at 04:16:31PM +0100, Maxime Ripard wrote:
> Start the big migration with drm.git.
> 
> Existing remotes need to be adjusted with
> 
> git remote set-url drm ssh://g...@gitlab.freedesktop.org:drm/kernel.git
> 
> or
> 
> git remote set-url drm https://gitlab.freedesktop.org/drm/kernel.git
> 
> Signed-off-by: Maxime Ripard 

Applied

Maxime


signature.asc
Description: PGP signature


Re: [PATCH v2 0/2] Fixes for omapdrm console

2024-02-26 Thread Thomas Zimmermann

Hi

Am 27.02.24 um 08:06 schrieb Tony Lindgren:

* Tony Lindgren  [240226 13:26]:

* Thomas Zimmermann  [240226 09:10]:

Am 26.02.24 um 10:01 schrieb Tomi Valkeinen:

On 26/02/2024 10:26, Tomi Valkeinen wrote:

How is it broken? I don't usually use the console (or fbdev) but
enabling it now, it seems to work fine for me, on DRA76 EVM with
HDMI output.

Omapdrm implements drm_framebuffer_funcs.dirty withomap_framebuffer_dirty().
AFAIK DRM semantics requires to run the dirty helper after writing to the
framebuffer's memory. Userspace does this via the DIRTYFB ioctl. [1] But (at
least) for correctness the console needs to do the same.

[1] 
https://elixir.bootlin.com/linux/v6.7.6/source/drivers/gpu/drm/drm_ioctl.c#L679

Yes I noticed console not updating and bisected it down to the two
commits listed. I did the bisect on a droid4 though with command mode
LCD. I did not test with HDMI, will give that a try too.

I can reproduce the cache issue with Tomi's omapfb-tests [2] below:

while true;
   do dd if=/dev/urandom of=/dev/fb0
   ~/src/omapfb-tests/test
   sleep 1
done

That produces short random data stripes on the test image.


After applying your patches, I see a lot of cache-related artifacts on
the screen when updating the fb.

I guess we might need a dma-specific mmap helper to make this work
correctly.

Comparing the difference between drm_gem_mmap_obj() and
fb_deferred_io_mmap(), the following test patch makes the cache issue
go away for me. Not sure if this can be set based on some flag, or if
we need a separate fb_deferred_io_wc_mmap() or something like that?

Regards,

Tony

[2] https://github.com/tomba/omapfb-tests

8< 
diff --git a/drivers/video/fbdev/core/fb_defio.c 
b/drivers/video/fbdev/core/fb_defio.c
--- a/drivers/video/fbdev/core/fb_defio.c
+++ b/drivers/video/fbdev/core/fb_defio.c
@@ -224,6 +224,7 @@ static const struct address_space_operations 
fb_deferred_io_aops = {
  int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
  {
vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
+   vma->vm_page_prot = 
pgprot_writecombine(vm_get_page_prot(vma->vm_flags));


Great, that's exactly what I had in mind!

My proposal is to add this mmap function directly to omapdrm. I'll later 
take care of integrating this into the overall framework. I have a few 
other ideas in mind that are related to this issue. Ok?


Best regards
Thomas

  
  	vma->vm_ops = _deferred_io_vm_ops;

vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP);


--
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)



Re: [PATCH 1/6] dt-bindings: gpu: powervr-rogue: Add PowerVR support for some Renesas GPUs

2024-02-26 Thread Geert Uytterhoeven
Hi Adam,

On Tue, Feb 27, 2024 at 4:46 AM Adam Ford  wrote:
> Update the binding to add support for various Renesas SoC's with PowerVR
> Rogue GX6250 and GX6650 GPUs.  These devices only need one clock, so update
> the table to indicate such like what was done for the ti,am62-gpu.
>
> Signed-off-by: Adam Ford 

Thanks for your patch!

> --- a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
> +++ b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
> @@ -14,6 +14,11 @@ properties:
>compatible:
>  items:
>- enum:
> +  - renesas,r8a774a1-gpu

I would add a comment like this:

- renesas,r8a774a1-gpu # PowerVR Series 6XT GX6650 on RZ/G2M

> +  - renesas,r8a774e1-gpu

.. # PowerVR Series 6XT GX6650 on RZ/G2H

> +  - renesas,r8a77951-gpu

... # PowerVR Series 6XT GX6650 on R-Car H3 ES2.0+

> +  - renesas,r8a77960-gpu

... # PowerVR Series 6XT GX6250 on R-Car M3-W

> +  - renesas,r8a77961-gpu

... # PowerVR Series 6XT GX6250 on R-Car M3-W+

>- ti,am62-gpu
>- const: img,img-axe # IMG AXE GPU model/revision is fully discoverable
>
> @@ -51,7 +56,13 @@ allOf:
>properties:
>  compatible:
>contains:
> -const: ti,am62-gpu
> +enum:
> +  - ti,am62-gpu
> +  - renesas,r8a774a1-gpu
> +  - renesas,r8a774e1-gpu
> +  - renesas,r8a77951-gpu
> +  - renesas,r8a77960-gpu
> +  - renesas,r8a77961-gpu

Please preserve alphabetical sort order.

>  then:
>properties:
>  clocks:
> --
> 2.43.0

Gr{oetje,eeting}s,

Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


Re: [PATCH] drm/mediatek: Fix a null pointer crash in mtk_drm_crtc_finish_page_flip

2024-02-26 Thread 胡俊光
Hi, Hsin-yi:

On Fri, 2024-02-23 at 13:23 -0800, Hsin-Yi Wang wrote:
External email : Please do not click links or open attachments until you have 
verified the sender or the content.

It's possible that mtk_crtc->event is NULL in

mtk_drm_crtc_finish_page_flip().


pending_needs_vblank value is set by mtk_crtc->event, but in

mtk_drm_crtc_atomic_flush(), it's is not guarded by the same

lock in mtk_drm_finish_page_flip(), thus a race condition happens.


Consider the following case:


CPU1  CPU2

step 1:

mtk_drm_crtc_atomic_begin()

mtk_crtc->event is not null,

  step 1:

  mtk_drm_crtc_atomic_flush:

  mtk_drm_crtc_update_config(

  !!mtk_crtc->event)

step 2:

mtk_crtc_ddp_irq ->

mtk_drm_finish_page_flip:

lock

mtk_crtc->event set to null,

pending_needs_vblank set to false

unlock

  pending_needs_vblank set to true,


  step 2:

  mtk_crtc_ddp_irq ->

  mtk_drm_finish_page_flip called again,

  pending_needs_vblank is still true

  //null pointer


Instead of guarding the entire mtk_drm_crtc_atomic_flush(), it's more

efficient to just check if mtk_crtc->event is null before use.


Signed-off-by: Hsin-Yi Wang mailto:hsi...@chromium.org>>

Fixes: 119f5173628a ("drm/mediatek: Add DRM Driver for Mediatek SoC MT8173.")


Reviewed-by: CK Hu 



---

 drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 12 +++-

 1 file changed, 7 insertions(+), 5 deletions(-)


diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c

index db43f9dff912..d645b85f9721 100644

--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c

+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c

@@ -95,11 +95,13 @@ static void mtk_drm_crtc_finish_page_flip(struct 
mtk_drm_crtc *mtk_crtc)

struct drm_crtc *crtc = _crtc->base;

unsigned long flags;



-   spin_lock_irqsave(>dev->event_lock, flags);

-   drm_crtc_send_vblank_event(crtc, mtk_crtc->event);

-   drm_crtc_vblank_put(crtc);

-   mtk_crtc->event = NULL;

-   spin_unlock_irqrestore(>dev->event_lock, flags);

+   if (mtk_crtc->event) {

+   spin_lock_irqsave(>dev->event_lock, flags);

+   drm_crtc_send_vblank_event(crtc, mtk_crtc->event);

+   drm_crtc_vblank_put(crtc);

+   mtk_crtc->event = NULL;

+   spin_unlock_irqrestore(>dev->event_lock, flags);

+   }

 }



 static void mtk_drm_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)

--

2.44.0.rc0.258.g7320e95886-goog



Re: [PATCH v5 00/14] drm: Add a driver for CSF-based Mali GPUs

2024-02-26 Thread Maxime Ripard
On Sun, 18 Feb 2024 22:41:14 +0100, Boris Brezillon wrote:
> Hello,
> 
> This is the 5th version of the kernel driver for Mali CSF-based GPUs,
> and, unless someone has good reasons to block the merging of this
> driver, I expect it to be the last one (the gallium driver is now
> 
> [ ... ]

Acked-by: Maxime Ripard 

Thanks!
Maxime


Re: [PATCH v2 0/2] Fixes for omapdrm console

2024-02-26 Thread Tony Lindgren
* Tony Lindgren  [240226 13:26]:
> * Thomas Zimmermann  [240226 09:10]:
> > Am 26.02.24 um 10:01 schrieb Tomi Valkeinen:
> > > On 26/02/2024 10:26, Tomi Valkeinen wrote:
> > > > How is it broken? I don't usually use the console (or fbdev) but
> > > > enabling it now, it seems to work fine for me, on DRA76 EVM with
> > > > HDMI output.
> > 
> > Omapdrm implements drm_framebuffer_funcs.dirty withomap_framebuffer_dirty().
> > AFAIK DRM semantics requires to run the dirty helper after writing to the
> > framebuffer's memory. Userspace does this via the DIRTYFB ioctl. [1] But (at
> > least) for correctness the console needs to do the same.
> > 
> > [1] 
> > https://elixir.bootlin.com/linux/v6.7.6/source/drivers/gpu/drm/drm_ioctl.c#L679
> 
> Yes I noticed console not updating and bisected it down to the two
> commits listed. I did the bisect on a droid4 though with command mode
> LCD. I did not test with HDMI, will give that a try too.

I can reproduce the cache issue with Tomi's omapfb-tests [2] below:

while true;
  do dd if=/dev/urandom of=/dev/fb0
  ~/src/omapfb-tests/test
  sleep 1
done

That produces short random data stripes on the test image.

> > > After applying your patches, I see a lot of cache-related artifacts on
> > > the screen when updating the fb.
> > 
> > I guess we might need a dma-specific mmap helper to make this work
> > correctly.

Comparing the difference between drm_gem_mmap_obj() and
fb_deferred_io_mmap(), the following test patch makes the cache issue
go away for me. Not sure if this can be set based on some flag, or if
we need a separate fb_deferred_io_wc_mmap() or something like that?

Regards,

Tony

[2] https://github.com/tomba/omapfb-tests

8< 
diff --git a/drivers/video/fbdev/core/fb_defio.c 
b/drivers/video/fbdev/core/fb_defio.c
--- a/drivers/video/fbdev/core/fb_defio.c
+++ b/drivers/video/fbdev/core/fb_defio.c
@@ -224,6 +224,7 @@ static const struct address_space_operations 
fb_deferred_io_aops = {
 int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
 {
vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
+   vma->vm_page_prot = 
pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
 
vma->vm_ops = _deferred_io_vm_ops;
vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP);


Re: Making drm_gpuvm work across gpu devices

2024-02-26 Thread Christian König

Hi Oak,

Am 23.02.24 um 21:12 schrieb Zeng, Oak:


Hi Christian,

I go back this old email to ask a question.



sorry totally missed that one.


Quote from your email:

“Those ranges can then be used to implement the SVM feature required 
for higher level APIs and not something you need at the UAPI or even 
inside the low level kernel memory management.”


“SVM is a high level concept of OpenCL, Cuda, ROCm etc.. This should 
not have any influence on the design of the kernel UAPI.”


There are two category of SVM:

 1. driver svm allocator: this is implemented in user space,  i.g.,
cudaMallocManaged (cuda) or zeMemAllocShared (L0) or
clSVMAlloc(openCL). Intel already have gem_create/vm_bind in xekmd
and our umd implemented clSVMAlloc and zeMemAllocShared on top of
gem_create/vm_bind. Range A..B of the process address space is
mapped into a range C..D of the GPU address space, exactly as you
said.
 2. system svm allocator:  This doesn’t introduce extra driver API for
memory allocation. Any valid CPU virtual address can be used
directly transparently in a GPU program without any extra driver
API call. Quote from kernel Documentation/vm/hmm.hst: “Any
application memory region (private anonymous, shared memory, or
regular file backed memory) can be used by a device transparently”
and “to share the address space by duplicating the CPU page table
in the device page table so the same address points to the same
physical memory for any valid main memory address in the process
address space”. In system svm allocator, we don’t need that A..B
C..D mapping.

It looks like you were talking of 1). Were you?



No, even when you fully mirror the whole address space from a process 
into the GPU you still need to enable this somehow with an IOCTL.


And while enabling this you absolutely should specify to which part of 
the address space this mirroring applies and where it maps to.


I see the system svm allocator as just a special case of the driver 
allocator where not fully backed buffer objects are allocated, but 
rather sparse one which are filled and migrated on demand.


Regards,
Christian.


Oak

*From:*Christian König 
*Sent:* Wednesday, January 24, 2024 3:33 AM
*To:* Zeng, Oak ; Danilo Krummrich 
; Dave Airlie ; Daniel Vetter 
; Felix Kuehling 
*Cc:* Welty, Brian ; 
dri-devel@lists.freedesktop.org; intel...@lists.freedesktop.org; 
Bommu, Krishnaiah ; Ghimiray, Himal Prasad 
; thomas.hellst...@linux.intel.com; 
Vishwanathapura, Niranjana ; 
Brost, Matthew ; Gupta, saurabhg 


*Subject:* Re: Making drm_gpuvm work across gpu devices

Am 23.01.24 um 20:37 schrieb Zeng, Oak:

[SNIP]

Yes most API are per device based.

One exception I know is actually the kfd SVM API. If you look at the 
svm_ioctl function, it is per-process based. Each kfd_process represent a 
process across N gpu devices.


Yeah and that was a big mistake in my opinion. We should really not do 
that ever again.



Need to say, kfd SVM represent a shared virtual address space across CPU 
and all GPU devices on the system. This is by the definition of SVM (shared 
virtual memory). This is very different from our legacy gpu *device* driver 
which works for only one device (i.e., if you want one device to access another 
device's memory, you will have to use dma-buf export/import etc).


Exactly that thinking is what we have currently found as blocker for a 
virtualization projects. Having SVM as device independent feature 
which somehow ties to the process address space turned out to be an 
extremely bad idea.


The background is that this only works for some use cases but not all 
of them.


What's working much better is to just have a mirror functionality 
which says that a range A..B of the process address space is mapped 
into a range C..D of the GPU address space.


Those ranges can then be used to implement the SVM feature required 
for higher level APIs and not something you need at the UAPI or even 
inside the low level kernel memory management.


When you talk about migrating memory to a device you also do this on a 
per device basis and *not* tied to the process address space. If you 
then get crappy performance because userspace gave contradicting 
information where to migrate memory then that's a bug in userspace and 
not something the kernel should try to prevent somehow.


[SNIP]

I think if you start using the same drm_gpuvm for multiple devices you

will sooner or later start to run into the same mess we have seen with

KFD, where we moved more and more functionality from the KFD to the DRM

render node because we found that a lot of the stuff simply doesn't work

correctly with a single object to maintain the state.

As I understand it, KFD is designed to work across devices. A single pseudo 
/dev/kfd device represent all hardware gpu devices. That is why during kfd 
open, many pdd (process device data) is 

[PATCH 2/4] drm: xlnx: zynqmp_dpsub: Anounce supported input formats

2024-02-26 Thread Anatoliy Klymenko
DPSUB in bridge mode supports multiple input media bus formats.

Announce the list of supported input media bus formats via
drm_bridge.atomic_get_input_bus_fmts callback.

Signed-off-by: Anatoliy Klymenko 
---
 drivers/gpu/drm/xlnx/zynqmp_disp.c | 37 +
 drivers/gpu/drm/xlnx/zynqmp_disp.h | 10 ++
 drivers/gpu/drm/xlnx/zynqmp_dp.c   |  1 +
 3 files changed, 48 insertions(+)

diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c 
b/drivers/gpu/drm/xlnx/zynqmp_disp.c
index e6d26ef60e89..ee99aad915ba 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -77,12 +78,14 @@ enum zynqmp_dpsub_layer_mode {
 /**
  * struct zynqmp_disp_format - Display subsystem format information
  * @drm_fmt: DRM format (4CC)
+ * @bus_fmt: Media bus format
  * @buf_fmt: AV buffer format
  * @swap: Flag to swap R & B for RGB formats, and U & V for YUV formats
  * @sf: Scaling factors for color components
  */
 struct zynqmp_disp_format {
u32 drm_fmt;
+   u32 bus_fmt;
u32 buf_fmt;
bool swap;
const u32 *sf;
@@ -364,6 +367,40 @@ static const struct zynqmp_disp_format avbuf_gfx_fmts[] = {
},
 };
 
+/* List of live video layer formats */
+static const struct zynqmp_disp_format avbuf_live_fmts[] = {
+   {
+   .drm_fmt= DRM_FORMAT_VYUY,
+   .bus_fmt= MEDIA_BUS_FMT_VYUY8_1X16,
+   .buf_fmt= ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 |
+ ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422,
+   .sf = scaling_factors_888,
+   },
+};
+
+u32 *zynqmp_disp_get_input_bus_fmts(struct drm_bridge *bridge,
+   struct drm_bridge_state *bridge_state,
+   struct drm_crtc_state *crtc_state,
+   struct drm_connector_state *conn_state,
+   u32 output_fmt,
+   unsigned int *num_input_fmts)
+{
+   int i;
+   u32 *input_fmts;
+
+   input_fmts = kcalloc(ARRAY_SIZE(avbuf_live_fmts), sizeof(*input_fmts), 
GFP_KERNEL);
+   if (!input_fmts) {
+   *num_input_fmts = 0;
+   return input_fmts;
+   }
+
+   for (i = 0; i < ARRAY_SIZE(avbuf_live_fmts); ++i)
+   input_fmts[i] =  avbuf_live_fmts[i].bus_fmt;
+   *num_input_fmts = ARRAY_SIZE(avbuf_live_fmts);
+
+   return input_fmts;
+}
+
 static u32 zynqmp_disp_avbuf_read(struct zynqmp_disp *disp, int reg)
 {
return readl(disp->avbuf.base + reg);
diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.h 
b/drivers/gpu/drm/xlnx/zynqmp_disp.h
index 9b8b202224d9..c2c8dd4896ba 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.h
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.h
@@ -27,6 +27,10 @@
 struct device;
 struct drm_format_info;
 struct drm_plane_state;
+struct drm_bridge;
+struct drm_bridge_state;
+struct drm_connector_state;
+struct drm_crtc_state;
 struct platform_device;
 struct zynqmp_disp;
 struct zynqmp_disp_layer;
@@ -52,6 +56,12 @@ void zynqmp_disp_blend_set_global_alpha(struct zynqmp_disp 
*disp,
 
 u32 *zynqmp_disp_layer_drm_formats(struct zynqmp_disp_layer *layer,
   unsigned int *num_formats);
+u32 *zynqmp_disp_get_input_bus_fmts(struct drm_bridge *bridge,
+   struct drm_bridge_state *bridge_state,
+   struct drm_crtc_state *crtc_state,
+   struct drm_connector_state *conn_state,
+   u32 output_fmt,
+   unsigned int *num_input_fmts);
 void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer);
 void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer);
 void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
index 04b6bcac3b07..9cb7ac9f3097 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
@@ -1580,6 +1580,7 @@ static const struct drm_bridge_funcs 
zynqmp_dp_bridge_funcs = {
.atomic_check = zynqmp_dp_bridge_atomic_check,
.detect = zynqmp_dp_bridge_detect,
.edid_read = zynqmp_dp_bridge_edid_read,
+   .atomic_get_input_bus_fmts = zynqmp_disp_get_input_bus_fmts,
 };
 
 /* 
-

-- 
2.25.1



[PATCH 1/4] drm: xlnx: zynqmp_dpsub: Set layer mode during creation

2024-02-26 Thread Anatoliy Klymenko
Set layer mode of operation (live or dma-based) during layer creation.

Each DPSUB layer mode of operation is defined by corresponding DT node port
connection, so it is possible to assign it during layer object creation.
Previously it was set in layer enable functions, although it is too late
as setting layer format depends on layer mode, and should be done before
given layer enabled.

Signed-off-by: Anatoliy Klymenko 
---
 drivers/gpu/drm/xlnx/zynqmp_disp.c | 20 
 drivers/gpu/drm/xlnx/zynqmp_disp.h | 13 +
 drivers/gpu/drm/xlnx/zynqmp_dp.c   |  2 +-
 drivers/gpu/drm/xlnx/zynqmp_kms.c  |  2 +-
 4 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c 
b/drivers/gpu/drm/xlnx/zynqmp_disp.c
index 8a39b3accce5..e6d26ef60e89 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c
@@ -64,6 +64,16 @@
 
 #define ZYNQMP_DISP_MAX_NUM_SUB_PLANES 3
 
+/**
+ * enum zynqmp_dpsub_layer_mode - Layer mode
+ * @ZYNQMP_DPSUB_LAYER_NONLIVE: non-live (memory) mode
+ * @ZYNQMP_DPSUB_LAYER_LIVE: live (stream) mode
+ */
+enum zynqmp_dpsub_layer_mode {
+   ZYNQMP_DPSUB_LAYER_NONLIVE,
+   ZYNQMP_DPSUB_LAYER_LIVE,
+};
+
 /**
  * struct zynqmp_disp_format - Display subsystem format information
  * @drm_fmt: DRM format (4CC)
@@ -902,15 +912,12 @@ u32 *zynqmp_disp_layer_drm_formats(struct 
zynqmp_disp_layer *layer,
 /**
  * zynqmp_disp_layer_enable - Enable a layer
  * @layer: The layer
- * @mode: Operating mode of layer
  *
  * Enable the @layer in the audio/video buffer manager and the blender. DMA
  * channels are started separately by zynqmp_disp_layer_update().
  */
-void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer,
- enum zynqmp_dpsub_layer_mode mode)
+void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer)
 {
-   layer->mode = mode;
zynqmp_disp_avbuf_enable_video(layer->disp, layer);
zynqmp_disp_blend_layer_enable(layer->disp, layer);
 }
@@ -1134,6 +1141,11 @@ static int zynqmp_disp_create_layers(struct zynqmp_disp 
*disp)
layer->id = i;
layer->disp = disp;
layer->info = _info[i];
+   /* For now assume dpsub works in either live or non-live mode 
for both layers.
+* Hybrid mode is not supported yet.
+*/
+   layer->mode = disp->dpsub->dma_enabled ? 
ZYNQMP_DPSUB_LAYER_NONLIVE
+  : 
ZYNQMP_DPSUB_LAYER_LIVE;
 
ret = zynqmp_disp_layer_request_dma(disp, layer);
if (ret)
diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.h 
b/drivers/gpu/drm/xlnx/zynqmp_disp.h
index 123cffac08be..9b8b202224d9 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.h
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.h
@@ -42,16 +42,6 @@ enum zynqmp_dpsub_layer_id {
ZYNQMP_DPSUB_LAYER_GFX,
 };
 
-/**
- * enum zynqmp_dpsub_layer_mode - Layer mode
- * @ZYNQMP_DPSUB_LAYER_NONLIVE: non-live (memory) mode
- * @ZYNQMP_DPSUB_LAYER_LIVE: live (stream) mode
- */
-enum zynqmp_dpsub_layer_mode {
-   ZYNQMP_DPSUB_LAYER_NONLIVE,
-   ZYNQMP_DPSUB_LAYER_LIVE,
-};
-
 void zynqmp_disp_enable(struct zynqmp_disp *disp);
 void zynqmp_disp_disable(struct zynqmp_disp *disp);
 int zynqmp_disp_setup_clock(struct zynqmp_disp *disp,
@@ -62,8 +52,7 @@ void zynqmp_disp_blend_set_global_alpha(struct zynqmp_disp 
*disp,
 
 u32 *zynqmp_disp_layer_drm_formats(struct zynqmp_disp_layer *layer,
   unsigned int *num_formats);
-void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer,
- enum zynqmp_dpsub_layer_mode mode);
+void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer);
 void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer);
 void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
  const struct drm_format_info *info);
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
index 1846c4971fd8..04b6bcac3b07 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
@@ -1295,7 +1295,7 @@ static void zynqmp_dp_disp_enable(struct zynqmp_dp *dp,
/* TODO: Make the format configurable. */
info = drm_format_info(DRM_FORMAT_YUV422);
zynqmp_disp_layer_set_format(layer, info);
-   zynqmp_disp_layer_enable(layer, ZYNQMP_DPSUB_LAYER_LIVE);
+   zynqmp_disp_layer_enable(layer);
 
if (layer_id == ZYNQMP_DPSUB_LAYER_GFX)
zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, true, 255);
diff --git a/drivers/gpu/drm/xlnx/zynqmp_kms.c 
b/drivers/gpu/drm/xlnx/zynqmp_kms.c
index db3bb4afbfc4..43bf416b33d5 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_kms.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_kms.c
@@ -122,7 +122,7 @@ static void zynqmp_dpsub_plane_atomic_update(struct 
drm_plane *plane,
 
/* Enable or 

[PATCH 3/4] drm: xlnx: zynqmp_dpsub: Set input live format

2024-02-26 Thread Anatoliy Klymenko
Program live video input format according to selected media bus format.

In the bridge mode of operation, DPSUB is connected to FPGA CRTC which
almost certainly supports a single media bus format as its output. Expect
this to be delivered via the new bridge atomic state. Program DPSUB
registers accordingly.

Signed-off-by: Anatoliy Klymenko 
---
 drivers/gpu/drm/xlnx/zynqmp_disp.c  | 52 +
 drivers/gpu/drm/xlnx/zynqmp_disp.h  |  2 ++
 drivers/gpu/drm/xlnx/zynqmp_disp_regs.h |  8 ++---
 drivers/gpu/drm/xlnx/zynqmp_dp.c| 13 ++---
 4 files changed, 67 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c 
b/drivers/gpu/drm/xlnx/zynqmp_disp.c
index ee99aad915ba..1c3ffdee6b8e 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c
@@ -416,6 +416,34 @@ static bool zynqmp_disp_layer_is_video(const struct 
zynqmp_disp_layer *layer)
return layer->id == ZYNQMP_DPSUB_LAYER_VID;
 }
 
+/**
+ * zynqmp_disp_avbuf_set_live_format - Set live input format for a layer
+ * @disp: Display controller
+ * @layer: The layer
+ * @fmt: The format information
+ *
+ * Set the live video input format for @layer to @fmt.
+ */
+static void zynqmp_disp_avbuf_set_live_format(struct zynqmp_disp *disp,
+ struct zynqmp_disp_layer *layer,
+ const struct zynqmp_disp_format 
*fmt)
+{
+   u32 reg, i;
+
+   reg = zynqmp_disp_layer_is_video(layer)
+   ? ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG
+   : ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG;
+   zynqmp_disp_avbuf_write(disp, reg, fmt->buf_fmt);
+
+   for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; ++i) {
+   reg = zynqmp_disp_layer_is_video(layer)
+   ? ZYNQMP_DISP_AV_BUF_LIVD_VID_COMP_SF(i)
+   : ZYNQMP_DISP_AV_BUF_LIVD_GFX_COMP_SF(i);
+   zynqmp_disp_avbuf_write(disp, reg, fmt->sf[i]);
+   }
+   layer->disp_fmt = fmt;
+}
+
 /**
  * zynqmp_disp_avbuf_set_format - Set the input format for a layer
  * @disp: Display controller
@@ -979,6 +1007,30 @@ void zynqmp_disp_layer_disable(struct zynqmp_disp_layer 
*layer)
zynqmp_disp_blend_layer_disable(layer->disp, layer);
 }
 
+/**
+ * zynqmp_disp_layer_set_live_format - Set live layer input format
+ * @layer: The layer
+ * @info: Input media bus format
+ *
+ * Set the live @layer input bus format. The layer must be disabled.
+ */
+void zynqmp_disp_layer_set_live_format(struct zynqmp_disp_layer *layer,
+  u32 bus_format)
+{
+   int i;
+   const struct zynqmp_disp_format *fmt;
+
+   for (i = 0; i < ARRAY_SIZE(avbuf_live_fmts); ++i) {
+   fmt = _live_fmts[i];
+   if (fmt->bus_fmt == bus_format) {
+   layer->disp_fmt = fmt;
+   layer->drm_fmt = drm_format_info(fmt->drm_fmt);
+   zynqmp_disp_avbuf_set_live_format(layer->disp, layer, 
fmt);
+   return;
+   }
+   }
+}
+
 /**
  * zynqmp_disp_layer_set_format - Set the layer format
  * @layer: The layer
diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.h 
b/drivers/gpu/drm/xlnx/zynqmp_disp.h
index c2c8dd4896ba..f244b7d2346a 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.h
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.h
@@ -66,6 +66,8 @@ void zynqmp_disp_layer_enable(struct zynqmp_disp_layer 
*layer);
 void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer);
 void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
  const struct drm_format_info *info);
+void zynqmp_disp_layer_set_live_format(struct zynqmp_disp_layer *layer,
+  u32 bus_format);
 int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer,
 struct drm_plane_state *state);
 
diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp_regs.h 
b/drivers/gpu/drm/xlnx/zynqmp_disp_regs.h
index f92a006d5070..fa3935384834 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp_regs.h
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp_regs.h
@@ -165,10 +165,10 @@
 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_10  0x2
 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_12  0x3
 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_MASKGENMASK(2, 0)
-#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB 0x0
-#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444  0x1
-#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422  0x2
-#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YONLY   0x3
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB (0x0 << 4)
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444  (0x1 << 4)
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422  (0x2 << 4)
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YONLY   (0x3 << 4)
 #define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_MASKGENMASK(5, 4)
 #define 

[PATCH 4/4] drm/atomic-helper: Add select_output_bus_format callback

2024-02-26 Thread Anatoliy Klymenko
Add select_output_bus_format to CRTC atomic helpers callbacks. This
callback Will allow CRTC to participate in media bus format negotiation
over connected DRM bridge chain and impose CRTC-specific restrictions.
A good example is CRTC implemented as FPGA soft IP. This kind of CRTC will
most certainly support a single output media bus format, as supporting
multiple runtime options consumes extra FPGA resources. A variety of
options for FPGA are usually achieved by synthesizing IP with different
parameters.

Incorporate select_output_bus_format callback into the format negotiation
stage to fix the input bus format of the first DRM bridge in the chain.

Signed-off-by: Anatoliy Klymenko 
---
 drivers/gpu/drm/drm_bridge.c | 19 +--
 include/drm/drm_modeset_helper_vtables.h | 31 +++
 2 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 521a71c61b16..453ae3d174b4 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -32,6 +32,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -879,7 +880,8 @@ static int select_bus_fmt_recursive(struct drm_bridge 
*first_bridge,
unsigned int i, num_in_bus_fmts = 0;
struct drm_bridge_state *cur_state;
struct drm_bridge *prev_bridge;
-   u32 *in_bus_fmts;
+   struct drm_crtc *crtc = crtc_state->crtc;
+   u32 *in_bus_fmts, in_fmt;
int ret;
 
prev_bridge = drm_bridge_get_prev_bridge(cur_bridge);
@@ -933,7 +935,20 @@ static int select_bus_fmt_recursive(struct drm_bridge 
*first_bridge,
return -ENOMEM;
 
if (first_bridge == cur_bridge) {
-   cur_state->input_bus_cfg.format = in_bus_fmts[0];
+   in_fmt = in_bus_fmts[0];
+   if (crtc->helper_private &&
+   crtc->helper_private->select_output_bus_format) {
+   in_fmt = crtc->helper_private->select_output_bus_format(
+   crtc,
+   crtc->state,
+   in_bus_fmts,
+   num_in_bus_fmts);
+   if (!in_fmt) {
+   kfree(in_bus_fmts);
+   return -ENOTSUPP;
+   }
+   }
+   cur_state->input_bus_cfg.format = in_fmt;
cur_state->output_bus_cfg.format = out_bus_fmt;
kfree(in_bus_fmts);
return 0;
diff --git a/include/drm/drm_modeset_helper_vtables.h 
b/include/drm/drm_modeset_helper_vtables.h
index 881b03e4dc28..7c21ae1fe3ad 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -489,6 +489,37 @@ struct drm_crtc_helper_funcs {
 bool in_vblank_irq, int *vpos, int *hpos,
 ktime_t *stime, ktime_t *etime,
 const struct drm_display_mode *mode);
+
+   /**
+* @select_output_bus_format
+*
+* Called by the first connected DRM bridge to negotiate input media
+* bus format. CRTC is expected to pick preferable media formats from
+* the list supported by the DRM bridge chain.
+*
+* This callback is optional.
+*
+* Parameters:
+*
+* crtc:
+* The CRTC.
+* crcs_state:
+* New CRTC state.
+* supported_fmts:
+* List of input bus formats supported by the bridge.
+* num_supported_fmts:
+* Number of formats in the list.
+*
+* Returns:
+*
+* Preferred bus format from the list or 0 if CRTC doesn't support any
+* from the provided list.
+*
+*/
+   u32 (*select_output_bus_format)(struct drm_crtc *crtc,
+   struct drm_crtc_state *crtc_state,
+   const u32 *supported_fmts,
+   int num_supported_fmts);
 };
 
 /**

-- 
2.25.1



[PATCH 0/4] Setting live video input format for ZynqMP DPSUB

2024-02-26 Thread Anatoliy Klymenko
Implement live video input format setting for ZynqMP DPSUB.

ZynqMP DPSUB can operate in 2 modes: DMA-based and live.

In the live mode, DPSUB receives a live video signal from FPGA-based CRTC.
DPSUB acts as a DRM encoder bridge in such a scenario. To properly tune
into the incoming video signal, DPSUB should be programmed with the proper
media bus format. This patch series addresses this task.

Patch 1/4: Set the DPSUB layer mode of operation prior to enabling the
layer. Allows to use layer operational mode before its enablement.

Patch 2/4: Announce supported input media bus formats via
drm_bridge_funcs.atomic_get_input_bus_fmts callback.

Patch 3/4: Program DPSUB live video input format based on selected bus
config in the new atomic bridge state.

Patch 4/4: New optional CRTC atomic helper proposal that will allow CRTC
to participate in DRM bridge chain format negotiation and impose format
restrictions. Incorporate this callback into the DRM bridge format
negotiation process.

Signed-off-by: Anatoliy Klymenko 
---
Anatoliy Klymenko (4):
  drm: xlnx: zynqmp_dpsub: Set layer mode during creation
  drm: xlnx: zynqmp_dpsub: Anounce supported input formats
  drm: xlnx: zynqmp_dpsub: Set input live format
  drm/atomic-helper: Add select_output_bus_format callback

 drivers/gpu/drm/drm_bridge.c |  19 +-
 drivers/gpu/drm/xlnx/zynqmp_disp.c   | 109 +--
 drivers/gpu/drm/xlnx/zynqmp_disp.h   |  25 +++
 drivers/gpu/drm/xlnx/zynqmp_disp_regs.h  |   8 +--
 drivers/gpu/drm/xlnx/zynqmp_dp.c |  16 +++--
 drivers/gpu/drm/xlnx/zynqmp_kms.c|   2 +-
 include/drm/drm_modeset_helper_vtables.h |  31 +
 7 files changed, 182 insertions(+), 28 deletions(-)
---
base-commit: bfa4437fd3938ae2e186e7664b2db65bb8775670
change-id: 20240226-dp-live-fmt-6415773b5a68

Best regards,
-- 
Anatoliy Klymenko 



[PATCH 4/6] arm64: dts: renesas: r8a77951: Enable GPU

2024-02-26 Thread Adam Ford
The GPU on the R-Car H3 is a Rogue GX6650 which uses firmware
rogue_4.46.6.61_v1.fw available from Imagination.

When enumerated, it appears as:
powervr fd00.gpu: [drm] loaded firmware powervr/rogue_4.46.6.62_v1.fw
powervr fd00.gpu: [drm] FW version v1.0 (build 6513336 OS)

Signed-off-by: Adam Ford 

diff --git a/arch/arm64/boot/dts/renesas/r8a77951.dtsi 
b/arch/arm64/boot/dts/renesas/r8a77951.dtsi
index bea4edd17d53..3e9defaeb00f 100644
--- a/arch/arm64/boot/dts/renesas/r8a77951.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77951.dtsi
@@ -2771,6 +2771,16 @@ gic: interrupt-controller@f101 {
resets = < 408>;
};
 
+   gpu: gpu@fd00 {
+   compatible = "renesas,r8a77951-gpu", "img,img-axe";
+   reg = <0 0xfd00 0 0x2>;
+   clocks = < CPG_MOD 112>;
+   clock-names = "core";
+   interrupts = ;
+   power-domains = < R8A7795_PD_3DG_E>;
+   resets = < 112>;
+   };
+
pciec0: pcie@fe00 {
compatible = "renesas,pcie-r8a7795",
 "renesas,pcie-rcar-gen3";
-- 
2.43.0



[PATCH 5/6] arm64: dts: renesas: r8a77960: Enable GPU

2024-02-26 Thread Adam Ford
The GPU on the R-Car M3-W is a Rogue GX6250 which uses firmware
rogue_4.45.2.58_v1.fw available from Imagination.

When enumerated, it appears as:
powervr fd00.gpu: [drm] loaded firmware powervr/rogue_4.45.2.58_v1.fw
powervr fd00.gpu: [drm] FW version v1.0 (build 6513336 OS)

Signed-off-by: Adam Ford 

diff --git a/arch/arm64/boot/dts/renesas/r8a77960.dtsi 
b/arch/arm64/boot/dts/renesas/r8a77960.dtsi
index 7846fea8e40d..0f17bc3f2d9a 100644
--- a/arch/arm64/boot/dts/renesas/r8a77960.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77960.dtsi
@@ -2558,6 +2558,16 @@ gic: interrupt-controller@f101 {
resets = < 408>;
};
 
+   gpu: gpu@fd00 {
+   compatible = "renesas,r8a77960-gpu", "img,img-axe";
+   reg = <0 0xfd00 0 0x2>;
+   clocks = < CPG_MOD 112>;
+   clock-names = "core";
+   interrupts = ;
+   power-domains = < R8A7796_PD_3DG_B>;
+   resets = < 112>;
+   };
+
pciec0: pcie@fe00 {
compatible = "renesas,pcie-r8a7796",
 "renesas,pcie-rcar-gen3";
-- 
2.43.0



[PATCH 6/6] arm64: dts: renesas: r8a77961: Enable GPU

2024-02-26 Thread Adam Ford
The GPU on the R-Car M3-W+ is a Rogue GX6250 which uses firmware
rogue_4.45.2.58_v1.fw available from Imagination.

When enumerated, it appears as:
powervr fd00.gpu: [drm] loaded firmware powervr/rogue_4.45.2.58_v1.fw
powervr fd00.gpu: [drm] FW version v1.0 (build 6513336 OS)

Signed-off-by: Adam Ford 

diff --git a/arch/arm64/boot/dts/renesas/r8a77961.dtsi 
b/arch/arm64/boot/dts/renesas/r8a77961.dtsi
index 58f9286a5ab5..cc17e624c069 100644
--- a/arch/arm64/boot/dts/renesas/r8a77961.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77961.dtsi
@@ -2438,6 +2438,16 @@ gic: interrupt-controller@f101 {
resets = < 408>;
};
 
+   gpu: gpu@fd00 {
+   compatible = "renesas,r8a77961-gpu", "img,img-axe";
+   reg = <0 0xfd00 0 0x2>;
+   clocks = < CPG_MOD 112>;
+   clock-names = "core";
+   interrupts = ;
+   power-domains = < R8A77961_PD_3DG_B>;
+   resets = < 112>;
+   };
+
pciec0: pcie@fe00 {
compatible = "renesas,pcie-r8a77961",
 "renesas,pcie-rcar-gen3";
-- 
2.43.0



[PATCH 3/6] arm64: dts: renesas: r8a774e1: Enable GPU

2024-02-26 Thread Adam Ford
The GPU on the RZ/G2H is a Rogue GX6650 which uses firmware
rogue_4.46.6.62_v1.fw available from Imagination.

When enumerated, it appears as:
 powervr fd00.gpu: [drm] loaded firmware powervr/rogue_4.46.6.62_v1.fw
 powervr fd00.gpu: [drm] FW version v1.0 (build 6513336 OS)

Signed-off-by: Adam Ford 

diff --git a/arch/arm64/boot/dts/renesas/r8a774e1.dtsi 
b/arch/arm64/boot/dts/renesas/r8a774e1.dtsi
index be55ae83944c..398c9df1577b 100644
--- a/arch/arm64/boot/dts/renesas/r8a774e1.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a774e1.dtsi
@@ -2464,6 +2464,16 @@ gic: interrupt-controller@f101 {
resets = < 408>;
};
 
+   gpu: gpu@fd00 {
+   compatible = "renesas,r8a774e1-gpu", "img,img-axe";
+   reg = <0 0xfd00 0 0x2>;
+   clocks = < CPG_MOD 112>;
+   clock-names = "core";
+   interrupts = ;
+   power-domains = < R8A774E1_PD_3DG_E>;
+   resets = < 112>;
+   };
+
pciec0: pcie@fe00 {
compatible = "renesas,pcie-r8a774e1",
 "renesas,pcie-rcar-gen3";
-- 
2.43.0



[PATCH 1/6] dt-bindings: gpu: powervr-rogue: Add PowerVR support for some Renesas GPUs

2024-02-26 Thread Adam Ford
Update the binding to add support for various Renesas SoC's with PowerVR
Rogue GX6250 and GX6650 GPUs.  These devices only need one clock, so update
the table to indicate such like what was done for the ti,am62-gpu.

Signed-off-by: Adam Ford 

diff --git a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml 
b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
index 256e252f8087..7c75104df09f 100644
--- a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
+++ b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
@@ -14,6 +14,11 @@ properties:
   compatible:
 items:
   - enum:
+  - renesas,r8a774a1-gpu
+  - renesas,r8a774e1-gpu
+  - renesas,r8a77951-gpu
+  - renesas,r8a77960-gpu
+  - renesas,r8a77961-gpu
   - ti,am62-gpu
   - const: img,img-axe # IMG AXE GPU model/revision is fully discoverable
 
@@ -51,7 +56,13 @@ allOf:
   properties:
 compatible:
   contains:
-const: ti,am62-gpu
+enum:
+  - ti,am62-gpu
+  - renesas,r8a774a1-gpu
+  - renesas,r8a774e1-gpu
+  - renesas,r8a77951-gpu
+  - renesas,r8a77960-gpu
+  - renesas,r8a77961-gpu
 then:
   properties:
 clocks:
-- 
2.43.0



[PATCH 0/6] gpu: powervr-rogue: Add PowerVR support for some Renesas devices

2024-02-26 Thread Adam Ford
Renesas has used a few variants of the Power VR GPU in their R-Car
and RZ/G2 families.  While there is still some work to do at the Mesa
level,  adding these device tree nodes allows the Power VR driver
to enumerate and load the respective firmware located:

https://gitlab.freedesktop.org/imagination/linux-firmware/-/tree/powervr/powervr?ref_type=heads

Adam Ford (6):
  dt-bindings: gpu: powervr-rogue: Add PowerVR support for some Renesas
GPUs
  arm64: dts: renesas: r8a774a1: Enable GPU
  arm64: dts: renesas: r8a774e1: Enable GPU
  arm64: dts: renesas: r8a77951: Enable GPU
  arm64: dts: renesas: r8a77960: Enable GPU
  arm64: dts: renesas: r8a77961: Enable GPU

 .../devicetree/bindings/gpu/img,powervr-rogue.yaml  | 13 -
 arch/arm64/boot/dts/renesas/r8a774a1.dtsi   | 10 ++
 arch/arm64/boot/dts/renesas/r8a774e1.dtsi   | 10 ++
 arch/arm64/boot/dts/renesas/r8a77951.dtsi   | 10 ++
 arch/arm64/boot/dts/renesas/r8a77960.dtsi   | 10 ++
 arch/arm64/boot/dts/renesas/r8a77961.dtsi   | 10 ++
 6 files changed, 62 insertions(+), 1 deletion(-)

-- 
2.43.0



[PATCH 2/6] arm64: dts: renesas: r8a774a1: Enable GPU

2024-02-26 Thread Adam Ford
The GPU on the RZ/G2M is a Rogue GX6250 which uses firmware
rogue_4.45.2.58_v1.fw available from Imagination.

When enumerated, it appears as:
  powervr fd00.gpu: [drm] loaded firmware powervr/rogue_4.45.2.58_v1.fw
  powervr fd00.gpu: [drm] FW version v1.0 (build 6513336 OS)

Signed-off-by: Adam Ford 

diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi 
b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
index a8a44fe5e83b..8923d9624b39 100644
--- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
@@ -2352,6 +2352,16 @@ gic: interrupt-controller@f101 {
resets = < 408>;
};
 
+   gpu: gpu@fd00 {
+   compatible = "renesas,r8a774a1-gpu", "img,img-axe";
+   reg = <0 0xfd00 0 0x2>;
+   clocks = < CPG_MOD 112>;
+   clock-names = "core";
+   interrupts = ;
+   power-domains = < R8A774A1_PD_3DG_B>;
+   resets = < 112>;
+   };
+
pciec0: pcie@fe00 {
compatible = "renesas,pcie-r8a774a1",
 "renesas,pcie-rcar-gen3";
-- 
2.43.0



Re: [PATCH RFC 00/12] drm/msm: add support for regenerating shipped xml.h headers

2024-02-26 Thread Masahiro Yamada
On Mon, Feb 26, 2024 at 7:49 PM Dmitry Baryshkov
 wrote:

> Could you please specify how you tried to compile the code? I can see
> warnings from headrgen2, but I'm really puzzled by the errors from the
> MSM driver itself.



I applied this patch set onto v6.8-rc6.


masahiro@zoe:~/ref/linux(testing7)$ git log --oneline  -15
40eb59f162cc (HEAD -> testing7) drm/msm: sync shipped headers database
ae850f45f243 drm/msm: tie regeneration of shipped headers
45401d4034ef drm/msm: import XML registers database
491e4d41308e drm/msm/headergen: generate _shipped files
6766c628c097 drm/msm/headergen: don't output full file paths
e48e9a8eaf21 drm/msm/headergen: use asprintf instead of custom aprintf
b12d6fb5d2a0 drm/msm/headergen: import source files from freedreno/envytools
4699358f5c5b drm/msm: use _shipped suffix for all xml.h files
295fcf923852 drm/msm/dsi: drop mmss_cc.xml.h
a15c0faba637 drm/msm/hdmi: drop qfprom.xml.h
6811afe14414 drm/msm/mdp5: add writeback block bases
feee4929582e kbuild: create destination directory for _shipped handling
d206a76d7d27 (tag: v6.8-rc6, origin/master, origin/HEAD, master) Linux 6.8-rc6
e231dbd452a7 Merge tag 'bcachefs-2024-02-25' of
https://evilpiepirate.org/git/bcachefs
5197728f8182 bcachefs: fix bch2_save_backtrace()


I see the build errors with arm64 defconfig.

[build step]

  $ git clean -fdx
  $ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
  $ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-  -j$(nproc)






As I commented in 05/12, -I$(srctree)/$(src) is lost.


I was able to build it with the following fix-up.



--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 ccflags-y := -I $(srctree)/$(src)
-ccflags-y := -I $(obj)/registers
+ccflags-y += -I $(obj)/registers
 ccflags-y += -I $(srctree)/$(src)/disp/dpu1
 ccflags-$(CONFIG_DRM_MSM_DSI) += -I $(srctree)/$(src)/dsi
 ccflags-$(CONFIG_DRM_MSM_DP) += -I $(srctree)/$(src)/dp






Better fixes would be to use #include "" properly.
It should be relative to the source file.






diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index 592b296aab22..cf878490abd0 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -9,7 +9,7 @@
 #include 
 #include 
 #include 
-#include "msm_drv.h"
+#include "../msm_drv.h"
 #include "a6xx_hfi.h"

 struct a6xx_gmu_bo {
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index c9c55e2ea584..3a109453db31 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -2,9 +2,9 @@
 /* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. */


-#include "msm_gem.h"
-#include "msm_mmu.h"
-#include "msm_gpu_trace.h"
+#include "../msm_gem.h"
+#include "../msm_mmu.h"
+#include "../msm_gpu_trace.h"
 #include "a6xx_gpu.h"
 #include "a6xx_gmu.xml.h"

diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index bc14df96feb0..007788bf38ce 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -12,7 +12,7 @@
 #include 
 #include 

-#include "msm_gpu.h"
+#include "../msm_gpu.h"

 #include "adreno_common.xml.h"
 #include "adreno_pm4.xml.h"









-- 
Best Regards
Masahiro Yamada


Re: [PATCH RFC 05/12] drm/msm: use _shipped suffix for all xml.h files

2024-02-26 Thread Masahiro Yamada
On Mon, Feb 26, 2024 at 11:11 AM Dmitry Baryshkov
 wrote:
>
> Move non-GPU xml.h files into the ./registers subdir and add the
> _shipped suffix. The GPU files are left intact for now, since they
> require processing via a gen_headers.py, while display headers are
> regenerated using headergen2
>
> Signed-off-by: Dmitry Baryshkov 
> ---
>  drivers/gpu/drm/msm/Makefile   | 53 
> ++
>  .../{dsi/dsi.xml.h => registers/dsi.xml.h_shipped} |  0
>  .../dsi_phy_10nm.xml.h_shipped}|  0
>  .../dsi_phy_14nm.xml.h_shipped}|  0
>  .../dsi_phy_20nm.xml.h_shipped}|  0
>  .../dsi_phy_28nm.xml.h_shipped}|  0
>  .../dsi_phy_28nm_8960.xml.h_shipped}   |  0
>  .../dsi_phy_7nm.xml.h_shipped} |  0
>  .../hdmi.xml.h => registers/hdmi.xml.h_shipped}|  0
>  .../mdp4.xml.h => registers/mdp4.xml.h_shipped}|  0
>  .../mdp5.xml.h => registers/mdp5.xml.h_shipped}|  0
>  .../mdp_common.xml.h_shipped}  |  0
>  .../sfpb.xml.h => registers/sfpb.xml.h_shipped}|  0
>  13 files changed, 43 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
> index 543e04fa72e3..89c9f5f93b85 100644
> --- a/drivers/gpu/drm/msm/Makefile
> +++ b/drivers/gpu/drm/msm/Makefile
> @@ -1,5 +1,6 @@
>  # SPDX-License-Identifier: GPL-2.0
>  ccflags-y := -I $(srctree)/$(src)
> +ccflags-y := -I $(obj)/registers


This accidentally overwrites ccflags-y defined above.
So, "-I $(srctree)/$(src)" is lost.



It should be

  ccflags-y += -I $(obj)/registers



I see several build errors.





-- 
Best Regards
Masahiro Yamada


Re: [PATCH 2/2] drm/panel: panel-edp: Match with panel hash for overridden modes

2024-02-26 Thread Dmitry Baryshkov
On Sat, 24 Feb 2024 at 00:40, Hsin-Yi Wang  wrote:
>
> It's found that some panels have variants that they share the same panel id
> although their EDID and names are different. One of the variants requires
> using overridden modes to resolve glitching issue as described in commit
> 70e0d5550f5c ("drm/panel-edp: Add auo_b116xa3_mode"). Other variants should
> use the modes parsed from EDID.
>
> For example, AUO 0x405c B116XAK01.0, it has at least 2 different variants
> that EDID and panel name are different, but using the same panel id. One of
> the variants require using overridden mode. Same case for AUO 0x615c
> B116XAN06.1.
>
> Add such entries and use the hash of the EDID to match the panel needs the
> overridden modes.
>
> Signed-off-by: Hsin-Yi Wang 
> ---
>  drivers/gpu/drm/panel/panel-edp.c | 52 +++
>  1 file changed, 46 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/panel/panel-edp.c 
> b/drivers/gpu/drm/panel/panel-edp.c
> index f6ddbaa103b5..42c430036846 100644
> --- a/drivers/gpu/drm/panel/panel-edp.c
> +++ b/drivers/gpu/drm/panel/panel-edp.c
> @@ -21,6 +21,7 @@
>   * DEALINGS IN THE SOFTWARE.
>   */
>
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -213,6 +214,9 @@ struct edp_panel_entry {
> /** @panel_id: 32-bit ID for panel, encoded with 
> drm_edid_encode_panel_id(). */
> u32 panel_id;
>
> +   /** @panel_hash: the CRC32 hash of the EDID base block. */
> +   u32 panel_hash;
> +
> /** @delay: The power sequencing delays needed for this panel. */
> const struct panel_delay *delay;
>
> @@ -758,13 +762,13 @@ static void panel_edp_parse_panel_timing_node(struct 
> device *dev,
> dev_err(dev, "Reject override mode: No display_timing 
> found\n");
>  }
>
> -static const struct edp_panel_entry *find_edp_panel(u32 panel_id);
> +static const struct edp_panel_entry *find_edp_panel(u32 panel_id, u32 
> panel_hash);
>
>  static int generic_edp_panel_probe(struct device *dev, struct panel_edp 
> *panel)
>  {
> struct panel_desc *desc;
> void *base_block;
> -   u32 panel_id;
> +   u32 panel_id, panel_hash;
> char vend[4];
> u16 product_id;
> u32 reliable_ms = 0;
> @@ -796,15 +800,17 @@ static int generic_edp_panel_probe(struct device *dev, 
> struct panel_edp *panel)
> base_block = drm_edid_get_base_block(panel->ddc);
> if (base_block) {
> panel_id = drm_edid_get_panel_id(base_block);
> +   panel_hash = crc32_le(~0, base_block, EDID_LENGTH) ^ 
> 0x;
> kfree(base_block);
> } else {
> dev_err(dev, "Couldn't identify panel via EDID\n");
> ret = -EIO;
> goto exit;
> }
> +
> drm_edid_decode_panel_id(panel_id, vend, _id);
>
> -   panel->detected_panel = find_edp_panel(panel_id);
> +   panel->detected_panel = find_edp_panel(panel_id, panel_hash);
>
> /*
>  * We're using non-optimized timings and want it really obvious that
> @@ -1006,6 +1012,19 @@ static const struct panel_desc auo_b101ean01 = {
> },
>  };
>
> +static const struct drm_display_mode auo_b116xa3_mode = {
> +   .clock = 70589,
> +   .hdisplay = 1366,
> +   .hsync_start = 1366 + 40,
> +   .hsync_end = 1366 + 40 + 40,
> +   .htotal = 1366 + 40 + 40 + 32,
> +   .vdisplay = 768,
> +   .vsync_start = 768 + 10,
> +   .vsync_end = 768 + 10 + 12,
> +   .vtotal = 768 + 10 + 12 + 6,
> +   .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
> +};
> +
>  static const struct drm_display_mode auo_b116xak01_mode = {
> .clock = 69300,
> .hdisplay = 1366,
> @@ -1926,11 +1945,13 @@ static const struct panel_delay 
> delay_200_500_e50_po2e200 = {
> .delay = _delay \
>  }
>
> -#define EDP_PANEL_ENTRY2(vend_chr_0, vend_chr_1, vend_chr_2, product_id, 
> _delay, _name, _mode) \
> +#define EDP_PANEL_ENTRY2(vend_chr_0, vend_chr_1, vend_chr_2, product_id, \
> +_hash, _delay, _name, _mode) \
>  { \
> .name = _name, \
> .panel_id = drm_edid_encode_panel_id(vend_chr_0, vend_chr_1, 
> vend_chr_2, \
>  product_id), \
> +   .panel_hash = _hash, \
> .delay = _delay, \
> .override_edid_mode = _mode \
>  }
> @@ -2077,13 +2098,32 @@ static const struct edp_panel_entry edp_panels[] = {
> { /* sentinal */ }
>  };
>
> -static const struct edp_panel_entry *find_edp_panel(u32 panel_id)
> +/*
> + * Similar to edp_panels, this table lists panel variants that require using
> + * overridden modes but have the same panel id as one of the entries in 
> edp_panels.
> + *
> + * Sort first by vendor, then by product ID.
> + */
> +static const struct edp_panel_entry edp_panels_variants[] = {

I'd suggest keeping these entries in the main table. Otherwise it
becomes harder to note, which setting gets 

Re: [PATCH 0/2] Match panel hash for overridden mode

2024-02-26 Thread Dmitry Baryshkov
On Tue, 27 Feb 2024 at 03:10, Hsin-Yi Wang  wrote:
>
> On Mon, Feb 26, 2024 at 4:37 PM Dmitry Baryshkov
>  wrote:
> >
> > On Sat, 24 Feb 2024 at 00:40, Hsin-Yi Wang  wrote:
> > >
> > > This series is a follow up for 1a5e81de180e ("Revert "drm/panel-edp: Add
> > > auo_b116xa3_mode""). It's found that 2 different AUO panels use the same
> > > product id. One of them requires an overridden mode, while the other 
> > > should
> > > use the mode directly from edid.
> > >
> > > Since product id match is no longer sufficient, EDP_PANEL_ENTRY2 is 
> > > extended
> > > to check the crc hash of the entire edid base block.
> >
> > Do you have these EDIDs posted somewhere? Can we use something less
> > cryptic than hash for matching the panel, e.g. strings from Monitor
> > Descriptors?
> >
>
> Panel 1:
>
> 00 ff ff ff ff ff ff 00 06 af 5c 40 00 00 00 00
> 00 1a 01 04 95 1a 0e 78 02 99 85 95 55 56 92 28
> 22 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01
> 01 01 01 01 01 01 12 1b 56 5a 50 00 19 30 30 20
> 46 00 00 90 10 00 00 18 00 00 00 0f 00 00 00 00
> 00 00 00 00 00 00 00 00 00 20 00 00 00 fe 00 41
> 55 4f 0a 20 20 20 20 20 20 20 20 20 00 00 00 fe
> 00 42 31 31 36 58 41 4b 30 31 2e 30 20 0a 00 cc
>
> 
>
> Block 0, Base EDID:
>   EDID Structure Version & Revision: 1.4
>   Vendor & Product Identification:
> Manufacturer: AUO
> Model: 16476
> Made in: 2016
>   Basic Display Parameters & Features:
> Digital display
> Bits per primary color channel: 6
> DisplayPort interface
> Maximum image size: 26 cm x 14 cm
> Gamma: 2.20
> Supported color formats: RGB 4:4:4
> First detailed timing includes the native pixel format and
> preferred refresh rate
>   Color Characteristics:
> Red  : 0.5839, 0.3330
> Green: 0.3378, 0.5712
> Blue : 0.1582, 0.1328
> White: 0.3134, 0.3291
>   Established Timings I & II: none
>   Standard Timings: none
>   Detailed Timing Descriptors:
> DTD 1:  1366x76860.020 Hz 683:384  47.596 kHz   69.300 MHz
> (256 mm x 144 mm)
>  Hfront   48 Hsync  32 Hback  10 Hpol N
>  Vfront4 Vsync   6 Vback  15 Vpol N
> Manufacturer-Specified Display Descriptor (0x0f): 00 0f 00 00 00
> 00 00 00 00 00 00 00 00 00 00 20 '... '
> Alphanumeric Data String: 'AUO'
> Alphanumeric Data String: 'B116XAK01.0 '
> Checksum: 0xcc
>
>
> Panel 2:
>
> 00 ff ff ff ff ff ff 00 06 af 5c 40 00 00 00 00
> 00 19 01 04 95 1a 0e 78 02 99 85 95 55 56 92 28
> 22 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01
> 01 01 01 01 01 01 ce 1d 56 ea 50 00 1a 30 30 20
> 46 00 00 90 10 00 00 18 d4 17 56 ea 50 00 1a 30
> 30 20 46 00 00 90 10 00 00 18 00 00 00 fe 00 41
> 55 4f 0a 20 20 20 20 20 20 20 20 20 00 00 00 fe
> 00 42 31 31 36 58 41 4e 30 34 2e 30 20 0a 00 94
>
> 
>
> Block 0, Base EDID:
>   EDID Structure Version & Revision: 1.4
>   Vendor & Product Identification:
> Manufacturer: AUO
> Model: 16476
> Made in: 2015
>   Basic Display Parameters & Features:
> Digital display
> Bits per primary color channel: 6
> DisplayPort interface
> Maximum image size: 26 cm x 14 cm
> Gamma: 2.20
> Supported color formats: RGB 4:4:4
> First detailed timing includes the native pixel format and
> preferred refresh rate
>   Color Characteristics:
> Red  : 0.5839, 0.3330
> Green: 0.3378, 0.5712
> Blue : 0.1582, 0.1328
> White: 0.3134, 0.3291
>   Established Timings I & II: none
>   Standard Timings: none
>   Detailed Timing Descriptors:
> DTD 1:  1366x76860.059824 Hz 683:384   47.688 kHz
> 76.30 MHz (256 mm x 144 mm)
>  Hfront   48 Hsync  32 Hback  154 Hpol N
>  Vfront4 Vsync   6 Vback   16 Vpol N
> DTD 2:  1366x76848.016373 Hz 683:384   38.125 kHz
> 61.00 MHz (256 mm x 144 mm)
>  Hfront   48 Hsync  32 Hback  154 Hpol N
>  Vfront4 Vsync   6 Vback   16 Vpol N
> Alphanumeric Data String: 'AUO'
> Alphanumeric Data String: 'B116XAN04.0 '
> Checksum: 0x94
>
> In this example, Descriptors can also be used to distinguish. But it's
> possible that the name field is also reused by mistake, for the same
> reason as model id is reused.

Thank you! Let's settle the discussion at the cover letter.

>
>
> > >
> > > Hsin-Yi Wang (2):
> > >   drm_edid: Add a function to get EDID base block
> > >   drm/panel: panel-edp: Match with panel hash for overridden modes
> > >
> > >  drivers/gpu/drm/drm_edid.c| 55 +++-
> > >  drivers/gpu/drm/panel/panel-edp.c | 60 ++-
> > >  include/drm/drm_edid.h|  3 +-
> > >  3 files changed, 84 insertions(+), 34 deletions(-)
> > >
> > > --
> > > 2.44.0.rc0.258.g7320e95886-goog
> > >
> >
> >
> > --
> > With best wishes
> > Dmitry



-- 
With best wishes
Dmitry


Re: [PATCH 0/2] Match panel hash for overridden mode

2024-02-26 Thread Dmitry Baryshkov
On Tue, 27 Feb 2024 at 03:00, Doug Anderson  wrote:
>
> Hi,
>
> On Mon, Feb 26, 2024 at 4:37 PM Dmitry Baryshkov
>  wrote:
> >
> > On Sat, 24 Feb 2024 at 00:40, Hsin-Yi Wang  wrote:
> > >
> > > This series is a follow up for 1a5e81de180e ("Revert "drm/panel-edp: Add
> > > auo_b116xa3_mode""). It's found that 2 different AUO panels use the same
> > > product id. One of them requires an overridden mode, while the other 
> > > should
> > > use the mode directly from edid.
> > >
> > > Since product id match is no longer sufficient, EDP_PANEL_ENTRY2 is 
> > > extended
> > > to check the crc hash of the entire edid base block.
> >
> > Do you have these EDIDs posted somewhere? Can we use something less
> > cryptic than hash for matching the panel, e.g. strings from Monitor
> > Descriptors?
>
> We could try it if need be. I guess I'm worried that if panel vendors
> ended up re-using the panel ID for two different panels that they
> might also re-use the name field too. Hashing the majority of the
> descriptor's base block makes us more likely not to mix two panels up.
> In general it feels like the goal is that if there is any doubt that
> we shouldn't override the mode and including more fields in the hash
> works towards that goal.

My main concern is that hash (or crc) is a non-obvious thing: even if
we have EDID in the commit message, it takes some effort to calculate
the value. If for any reason we decide to change the hashed bytes
(e.g. by dropping any of the fields) it will be an error-prone process
to update existing hash values. On the contrary, the 'strings' are
easy to check / compare without any additional tools.

>
> I guess one thing that might help would be to make it a policy that
> any time a panel is added to this list that a full EDID is included in
> the commit message. That would mean that if we ever needed to change
> things we could. What do you think?

Definitely, that sounds like a good idea.

> That being said, if everyone thinks that the "name" field is enough,
> we could do it. I think that in the one case that we ran into it would
> have been enough...

Yes, I'd suggest using the string unless at some point we see two
panels sharing both panel_id and names.

-- 
With best wishes
Dmitry


Re: [PATCH next v2 03/11] minmax: Simplify signedness check

2024-02-26 Thread kernel test robot
Hi David,

kernel test robot noticed the following build warnings:

[auto build test WARNING on drm-misc/drm-misc-next]
[also build test WARNING on linux/master mkl-can-next/testing kdave/for-next 
akpm-mm/mm-nonmm-unstable axboe-block/for-next linus/master v6.8-rc6 
next-20240226]
[cannot apply to next-20240223 dtor-input/next dtor-input/for-linus 
horms-ipvs/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:
https://github.com/intel-lab-lkp/linux/commits/David-Laight/minmax-Put-all-the-clamp-definitions-together/20240226-005902
base:   git://anongit.freedesktop.org/drm/drm-misc drm-misc-next
patch link:
https://lore.kernel.org/r/8657dd5c2264456f8a005520a3b90e2b%40AcuMS.aculab.com
patch subject: [PATCH next v2 03/11] minmax: Simplify signedness check
config: alpha-defconfig 
(https://download.01.org/0day-ci/archive/20240227/202402270937.9kmo5pft-...@intel.com/config)
compiler: alpha-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): 
(https://download.01.org/0day-ci/archive/20240227/202402270937.9kmo5pft-...@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot 
| Closes: 
https://lore.kernel.org/oe-kbuild-all/202402270937.9kmo5pft-...@intel.com/

All warnings (new ones prefixed by >>):

   In file included from include/linux/kernel.h:28,
from include/linux/cpumask.h:10,
from include/linux/smp.h:13,
from include/linux/lockdep.h:14,
from include/linux/spinlock.h:63,
from include/linux/swait.h:7,
from include/linux/completion.h:12,
from include/linux/crypto.h:15,
from include/crypto/aead.h:13,
from include/crypto/internal/aead.h:11,
from crypto/skcipher.c:12:
   crypto/skcipher.c: In function 'skcipher_get_spot':
>> include/linux/minmax.h:31:70: warning: ordered comparison of pointer with 
>> integer zero [-Wextra]
  31 | (is_unsigned_type(typeof(x)) || (__is_constexpr(x) ? (x) + 0 
>= 0 : 0))
 |  
^~
   include/linux/minmax.h:39:11: note: in expansion of macro '__is_ok_unsigned'
  39 |  (__is_ok_unsigned(x) && __is_ok_unsigned(y)))
 |   ^~~~
   include/linux/minmax.h:49:24: note: in expansion of macro '__types_ok'
  49 | _Static_assert(__types_ok(x, y),\
 |^~
   include/linux/minmax.h:56:17: note: in expansion of macro '__cmp_once'
  56 | __cmp_once(op, x, y, __UNIQUE_ID(__x), 
__UNIQUE_ID(__y)))
 | ^~
   include/linux/minmax.h:70:25: note: in expansion of macro '__careful_cmp'
  70 | #define max(x, y)   __careful_cmp(max, x, y)
 | ^
   crypto/skcipher.c:83:16: note: in expansion of macro 'max'
  83 | return max(start, end_page);
 |^~~
>> include/linux/minmax.h:31:70: warning: ordered comparison of pointer with 
>> integer zero [-Wextra]
  31 | (is_unsigned_type(typeof(x)) || (__is_constexpr(x) ? (x) + 0 
>= 0 : 0))
 |  
^~
   include/linux/minmax.h:39:34: note: in expansion of macro '__is_ok_unsigned'
  39 |  (__is_ok_unsigned(x) && __is_ok_unsigned(y)))
 |  ^~~~
   include/linux/minmax.h:49:24: note: in expansion of macro '__types_ok'
  49 | _Static_assert(__types_ok(x, y),\
 |^~
   include/linux/minmax.h:56:17: note: in expansion of macro '__cmp_once'
  56 | __cmp_once(op, x, y, __UNIQUE_ID(__x), 
__UNIQUE_ID(__y)))
 | ^~
   include/linux/minmax.h:70:25: note: in expansion of macro '__careful_cmp'
  70 | #define max(x, y)   __careful_cmp(max, x, y)
 | ^
   crypto/skcipher.c:83:16: note: in expansion of macro 'max'
  83 | return max(start, end_page);
 |^~~


vim +31 include/linux/minmax.h

 9  
10  /*
11   * min()/max()/clamp() macros must accomplish several things:
12   *
13   * - Avoid multiple evaluations of the arguments (so side-effects like
14   *   "x++" happen only once) when non-constant.
15   * - Retain result as a constant expressions when called with only
16   *   constant expressions (to avoi

Re: [PATCH 0/2] Match panel hash for overridden mode

2024-02-26 Thread Hsin-Yi Wang
On Mon, Feb 26, 2024 at 4:37 PM Dmitry Baryshkov
 wrote:
>
> On Sat, 24 Feb 2024 at 00:40, Hsin-Yi Wang  wrote:
> >
> > This series is a follow up for 1a5e81de180e ("Revert "drm/panel-edp: Add
> > auo_b116xa3_mode""). It's found that 2 different AUO panels use the same
> > product id. One of them requires an overridden mode, while the other should
> > use the mode directly from edid.
> >
> > Since product id match is no longer sufficient, EDP_PANEL_ENTRY2 is extended
> > to check the crc hash of the entire edid base block.
>
> Do you have these EDIDs posted somewhere? Can we use something less
> cryptic than hash for matching the panel, e.g. strings from Monitor
> Descriptors?
>

Panel 1:

00 ff ff ff ff ff ff 00 06 af 5c 40 00 00 00 00
00 1a 01 04 95 1a 0e 78 02 99 85 95 55 56 92 28
22 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 12 1b 56 5a 50 00 19 30 30 20
46 00 00 90 10 00 00 18 00 00 00 0f 00 00 00 00
00 00 00 00 00 00 00 00 00 20 00 00 00 fe 00 41
55 4f 0a 20 20 20 20 20 20 20 20 20 00 00 00 fe
00 42 31 31 36 58 41 4b 30 31 2e 30 20 0a 00 cc



Block 0, Base EDID:
  EDID Structure Version & Revision: 1.4
  Vendor & Product Identification:
Manufacturer: AUO
Model: 16476
Made in: 2016
  Basic Display Parameters & Features:
Digital display
Bits per primary color channel: 6
DisplayPort interface
Maximum image size: 26 cm x 14 cm
Gamma: 2.20
Supported color formats: RGB 4:4:4
First detailed timing includes the native pixel format and
preferred refresh rate
  Color Characteristics:
Red  : 0.5839, 0.3330
Green: 0.3378, 0.5712
Blue : 0.1582, 0.1328
White: 0.3134, 0.3291
  Established Timings I & II: none
  Standard Timings: none
  Detailed Timing Descriptors:
DTD 1:  1366x76860.020 Hz 683:384  47.596 kHz   69.300 MHz
(256 mm x 144 mm)
 Hfront   48 Hsync  32 Hback  10 Hpol N
 Vfront4 Vsync   6 Vback  15 Vpol N
Manufacturer-Specified Display Descriptor (0x0f): 00 0f 00 00 00
00 00 00 00 00 00 00 00 00 00 20 '... '
Alphanumeric Data String: 'AUO'
Alphanumeric Data String: 'B116XAK01.0 '
Checksum: 0xcc


Panel 2:

00 ff ff ff ff ff ff 00 06 af 5c 40 00 00 00 00
00 19 01 04 95 1a 0e 78 02 99 85 95 55 56 92 28
22 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 ce 1d 56 ea 50 00 1a 30 30 20
46 00 00 90 10 00 00 18 d4 17 56 ea 50 00 1a 30
30 20 46 00 00 90 10 00 00 18 00 00 00 fe 00 41
55 4f 0a 20 20 20 20 20 20 20 20 20 00 00 00 fe
00 42 31 31 36 58 41 4e 30 34 2e 30 20 0a 00 94



Block 0, Base EDID:
  EDID Structure Version & Revision: 1.4
  Vendor & Product Identification:
Manufacturer: AUO
Model: 16476
Made in: 2015
  Basic Display Parameters & Features:
Digital display
Bits per primary color channel: 6
DisplayPort interface
Maximum image size: 26 cm x 14 cm
Gamma: 2.20
Supported color formats: RGB 4:4:4
First detailed timing includes the native pixel format and
preferred refresh rate
  Color Characteristics:
Red  : 0.5839, 0.3330
Green: 0.3378, 0.5712
Blue : 0.1582, 0.1328
White: 0.3134, 0.3291
  Established Timings I & II: none
  Standard Timings: none
  Detailed Timing Descriptors:
DTD 1:  1366x76860.059824 Hz 683:384   47.688 kHz
76.30 MHz (256 mm x 144 mm)
 Hfront   48 Hsync  32 Hback  154 Hpol N
 Vfront4 Vsync   6 Vback   16 Vpol N
DTD 2:  1366x76848.016373 Hz 683:384   38.125 kHz
61.00 MHz (256 mm x 144 mm)
 Hfront   48 Hsync  32 Hback  154 Hpol N
 Vfront4 Vsync   6 Vback   16 Vpol N
Alphanumeric Data String: 'AUO'
Alphanumeric Data String: 'B116XAN04.0 '
Checksum: 0x94

In this example, Descriptors can also be used to distinguish. But it's
possible that the name field is also reused by mistake, for the same
reason as model id is reused.


> >
> > Hsin-Yi Wang (2):
> >   drm_edid: Add a function to get EDID base block
> >   drm/panel: panel-edp: Match with panel hash for overridden modes
> >
> >  drivers/gpu/drm/drm_edid.c| 55 +++-
> >  drivers/gpu/drm/panel/panel-edp.c | 60 ++-
> >  include/drm/drm_edid.h|  3 +-
> >  3 files changed, 84 insertions(+), 34 deletions(-)
> >
> > --
> > 2.44.0.rc0.258.g7320e95886-goog
> >
>
>
> --
> With best wishes
> Dmitry


Re: [PATCH 2/2] fbcon: Defer console takeover for splash screens to first switch

2024-02-26 Thread Daniel van Vugt
On 27/2/24 02:23, Hans de Goede wrote:
> Hi All,
> 
> On 2/2/24 09:53, Daniel van Vugt wrote:
>> Until now, deferred console takeover only meant defer until there is
>> output. But that risks stepping on the toes of userspace splash screens,
>> as console messages may appear before the splash screen. So check for the
>> "splash" parameter (as used by Plymouth) and if present then extend the
>> deferral until the first switch.
> 
> Daniel, thank you for your patch but I do not believe that this
> is the right solution. Deferring fbcon takeover further then
> after the first text is output means that any errors about e.g.
> a corrupt initrd or the kernel erroring out / crashing will not
> be visible.

That's not really correct. If a boot failure has occurred after the splash then
pressing escape shows the log. If a boot failure has occurred before the splash
then it can be debugged visually by rebooting without the "splash" parameter.

> 
> When the kernel e.g. oopses or panics because of not finding
> its rootfs (I tested the latter option when writing the original
> deferred fbcon takeover code) then fbcon must takeover and
> print the messages from the dying kernel so that the user has
> some notion of what is going wrong.

Indeed, just reboot without the "splash" parameter to do that.

> 
> And since your patch seems to delay switching till the first
> vc-switch this means that e.g. even after say gdm refusing
> to start because of issues there still will be no text
> output. This makes debugging various issues much harder.

I've debugged many gdm failures and it is never useful to use the console for
those. Reboot and get the system journal instead.

> 
> Moreover Fedora has been doing flickerfree boot for many
> years without needing this.

I believe Fedora has a mostly working solution, but not totally reliable, as
mentioned in the commit message:

"even systems whose splash exists in initrd may not be not immune because they
 still rely on racing against all possible kernel messages that might
 trigger the fbcon takeover"

> 
> The kernel itself will be quiet as long as you set
> CONFIG_CONSOLE_LOGLEVEL_QUIET=3 Ubuntu atm has set this
> to 4 which means any kernel pr_err() or dev_err()
> messages will get through and since there are quite
> a few false positives of those Ubuntu really needs
> to set CONFIG_CONSOLE_LOGLEVEL_QUIET=3 to fix part of:
> https://bugs.launchpad.net/bugs/1970069

Incorrect. In my testing some laptops needed log level as low as 2 to go quiet.
And the Ubuntu kernel team is never going to fix all those for non-sponsored
devices.

> 
> After that it is "just" a matter of not making userspace
> output anything unless it has errors to report.
> 
> systemd already is quiet by default (only logging
> errors) when quiet is on the kernel commandline.

Unfortunately not true for Ubuntu. We carry a noisy systemd patch which I'm
told we can't remove in the short term:

https://bugs.launchpad.net/ubuntu/+source/plymouth/+bug/1970069/comments/39

> 
> So any remaining issues are Ubuntu specific boot
> process bits and Ubuntu really should be able to
> make those by silent unless they have important
> info (errors or other unexpected things) to report.
> 
> Given that this will make debugging boot issues
> much harder and that there are other IMHO better
> alternatives I'm nacking this patch: NACK.
> 
> FWIW I believe that I'm actually saving Ubuntu
> from shooting themselves in the foot here,
> hiding all sort of boot errors (like the initrd
> not finding /) until the user does a magic
> alt+f2 followed by alt+f1 incantation really is
> not doing yourself any favors wrt debugging any
> sort of boot failures.
> 
> Regards,
> 
> Hans

Thanks for your input, but I respectfully disagree and did consider these
points already.

- Daniel

> 
> 
> 
> 
> 
>> Closes: https://bugs.launchpad.net/bugs/1970069
>> Cc: Mario Limonciello 
>> Signed-off-by: Daniel van Vugt 
>> ---
>>  drivers/video/fbdev/core/fbcon.c | 32 +---
>>  1 file changed, 29 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/video/fbdev/core/fbcon.c 
>> b/drivers/video/fbdev/core/fbcon.c
>> index 63af6ab034..5b9f7635f7 100644
>> --- a/drivers/video/fbdev/core/fbcon.c
>> +++ b/drivers/video/fbdev/core/fbcon.c
>> @@ -76,6 +76,7 @@
>>  #include  /* For counting font checksums */
>>  #include 
>>  #include 
>> +#include 
>>  
>>  #include "fbcon.h"
>>  #include "fb_internal.h"
>> @@ -146,6 +147,7 @@ static inline void fbcon_map_override(void)
>>  
>>  #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER
>>  static bool deferred_takeover = true;
>> +static int initial_console = -1;
>>  #else
>>  #define deferred_takeover false
>>  #endif
>> @@ -3341,7 +3343,7 @@ static void fbcon_register_existing_fbs(struct 
>> work_struct *work)
>>  console_unlock();
>>  }
>>  
>> -static struct notifier_block fbcon_output_nb;
>> +static struct notifier_block fbcon_output_nb, fbcon_switch_nb;
>>  static 

Re: linux-next: Tree for Feb 26 (drivers/gpu/drm/xe)

2024-02-26 Thread Randy Dunlap



On 2/25/24 22:55, Stephen Rothwell wrote:
> Hi all,
> 
> Changes since 20240223:
> 

on powerpc32 or i386:

../drivers/gpu/drm/xe/xe_ggtt.c: In function 'xe_ggtt_set_pte':
../drivers/gpu/drm/xe/xe_ggtt.c:78:9: error: implicit declaration of function 
'writeq'; did you mean 'writel'? [-Werror=implicit-function-declaration]
   78 | writeq(pte, >gsm[addr >> XE_PTE_SHIFT]);
  | ^~
  | writel


-- 
#Randy


Re: [PATCH 0/2] Match panel hash for overridden mode

2024-02-26 Thread Doug Anderson
Hi,

On Mon, Feb 26, 2024 at 4:37 PM Dmitry Baryshkov
 wrote:
>
> On Sat, 24 Feb 2024 at 00:40, Hsin-Yi Wang  wrote:
> >
> > This series is a follow up for 1a5e81de180e ("Revert "drm/panel-edp: Add
> > auo_b116xa3_mode""). It's found that 2 different AUO panels use the same
> > product id. One of them requires an overridden mode, while the other should
> > use the mode directly from edid.
> >
> > Since product id match is no longer sufficient, EDP_PANEL_ENTRY2 is extended
> > to check the crc hash of the entire edid base block.
>
> Do you have these EDIDs posted somewhere? Can we use something less
> cryptic than hash for matching the panel, e.g. strings from Monitor
> Descriptors?

We could try it if need be. I guess I'm worried that if panel vendors
ended up re-using the panel ID for two different panels that they
might also re-use the name field too. Hashing the majority of the
descriptor's base block makes us more likely not to mix two panels up.
In general it feels like the goal is that if there is any doubt that
we shouldn't override the mode and including more fields in the hash
works towards that goal.

I guess one thing that might help would be to make it a policy that
any time a panel is added to this list that a full EDID is included in
the commit message. That would mean that if we ever needed to change
things we could. What do you think?

That being said, if everyone thinks that the "name" field is enough,
we could do it. I think that in the one case that we ran into it would
have been enough...

-Doug


Re: [syzbot] [dri?] [media?] inconsistent lock state in valid_state (2)

2024-02-26 Thread syzbot
syzbot has found a reproducer for the following issue on:

HEAD commit:d206a76d7d27 Linux 6.8-rc6
git tree:   upstream
console+strace: https://syzkaller.appspot.com/x/log.txt?x=12eea10618
kernel config:  https://syzkaller.appspot.com/x/.config?x=fad652894fc96962
dashboard link: https://syzkaller.appspot.com/bug?extid=a225ee3df7e7f9372dbe
compiler:   Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 
2.40
syz repro:  https://syzkaller.appspot.com/x/repro.syz?x=1537934a18
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=1704b3e218

Downloadable assets:
disk image: 
https://storage.googleapis.com/syzbot-assets/6fa98109295d/disk-d206a76d.raw.xz
vmlinux: 
https://storage.googleapis.com/syzbot-assets/613b4087d09d/vmlinux-d206a76d.xz
kernel image: 
https://storage.googleapis.com/syzbot-assets/d8cd6514daf9/bzImage-d206a76d.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+a225ee3df7e7f9372...@syzkaller.appspotmail.com


WARNING: inconsistent lock state
6.8.0-rc6-syzkaller #0 Not tainted

inconsistent {HARDIRQ-ON-W} -> {IN-HARDIRQ-W} usage.
syz-executor120/5070 [HC1[1]:SC0[0]:HE0:SE1] takes:
8ea8cd18 (sync_timeline_list_lock){?.+.}-{2:2}, at: 
sync_timeline_debug_remove+0x2c/0x150 drivers/dma-buf/sync_debug.c:31
{HARDIRQ-ON-W} state was registered at:
  trace_hardirqs_on+0x28/0x40 kernel/trace/trace_preemptirq.c:61
  __raw_spin_unlock_irq include/linux/spinlock_api_smp.h:159 [inline]
  _raw_spin_unlock_irq+0x23/0x50 kernel/locking/spinlock.c:202
  spin_unlock_irq include/linux/spinlock.h:401 [inline]
  sync_print_obj drivers/dma-buf/sync_debug.c:118 [inline]
  sync_info_debugfs_show+0x158/0x4d0 drivers/dma-buf/sync_debug.c:153
  seq_read_iter+0x445/0xd60 fs/seq_file.c:230
  seq_read+0x3a3/0x4f0 fs/seq_file.c:162
  vfs_read+0x204/0xb70 fs/read_write.c:474
  ksys_read+0x1a0/0x2c0 fs/read_write.c:619
  do_syscall_64+0xf9/0x240
  entry_SYSCALL_64_after_hwframe+0x6f/0x77
irq event stamp: 9608
hardirqs last  enabled at (9607): [] __raw_spin_unlock_irq 
include/linux/spinlock_api_smp.h:159 [inline]
hardirqs last  enabled at (9607): [] 
_raw_spin_unlock_irq+0x23/0x50 kernel/locking/spinlock.c:202
hardirqs last disabled at (9608): [] sysvec_irq_work+0xe/0xb0 
arch/x86/kernel/irq_work.c:17
softirqs last  enabled at (9124): [] invoke_softirq 
kernel/softirq.c:427 [inline]
softirqs last  enabled at (9124): [] 
__irq_exit_rcu+0xf1/0x1c0 kernel/softirq.c:632
softirqs last disabled at (9119): [] invoke_softirq 
kernel/softirq.c:427 [inline]
softirqs last disabled at (9119): [] 
__irq_exit_rcu+0xf1/0x1c0 kernel/softirq.c:632

other info that might help us debug this:
 Possible unsafe locking scenario:

   CPU0
   
  lock(sync_timeline_list_lock);
  
lock(sync_timeline_list_lock);

 *** DEADLOCK ***

no locks held by syz-executor120/5070.

stack backtrace:
CPU: 0 PID: 5070 Comm: syz-executor120 Not tainted 6.8.0-rc6-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 
01/25/2024
Call Trace:
 
 __dump_stack lib/dump_stack.c:88 [inline]
 dump_stack_lvl+0x1e7/0x2e0 lib/dump_stack.c:106
 valid_state+0x13a/0x1c0 kernel/locking/lockdep.c:4013
 mark_lock_irq+0xbb/0xc20 kernel/locking/lockdep.c:4216
 mark_lock+0x223/0x350 kernel/locking/lockdep.c:4678
 mark_usage kernel/locking/lockdep.c:4564 [inline]
 __lock_acquire+0xb8d/0x1fd0 kernel/locking/lockdep.c:5091
 lock_acquire+0x1e3/0x530 kernel/locking/lockdep.c:5754
 __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline]
 _raw_spin_lock_irqsave+0xd5/0x120 kernel/locking/spinlock.c:162
 sync_timeline_debug_remove+0x2c/0x150 drivers/dma-buf/sync_debug.c:31
 sync_timeline_free drivers/dma-buf/sw_sync.c:125 [inline]
 kref_put include/linux/kref.h:65 [inline]
 sync_timeline_put drivers/dma-buf/sw_sync.c:137 [inline]
 timeline_fence_release+0x204/0x250 drivers/dma-buf/sw_sync.c:165
 kref_put include/linux/kref.h:65 [inline]
 dma_fence_put include/linux/dma-fence.h:297 [inline]
 dma_fence_array_release+0x13e/0x240 drivers/dma-buf/dma-fence-array.c:120
 irq_work_single+0xe1/0x240 kernel/irq_work.c:221
 irq_work_run_list kernel/irq_work.c:252 [inline]
 irq_work_run+0x18b/0x350 kernel/irq_work.c:261
 __sysvec_irq_work+0xa8/0x3e0 arch/x86/kernel/irq_work.c:22
 sysvec_irq_work+0x8f/0xb0 arch/x86/kernel/irq_work.c:17
 
 
 asm_sysvec_irq_work+0x1a/0x20 arch/x86/include/asm/idtentry.h:674
RIP: 0010:__raw_spin_unlock_irq include/linux/spinlock_api_smp.h:160 [inline]
RIP: 0010:_raw_spin_unlock_irq+0x29/0x50 kernel/locking/spinlock.c:202
Code: 90 f3 0f 1e fa 53 48 89 fb 48 83 c7 18 48 8b 74 24 08 e8 da 4b ff f5 48 
89 df e8 92 8b 00 f6 e8 ad aa 28 f6 fb bf 01 00 00 00  62 5c f2 f5 65 8b 05 
e3 cd 91 74 85 c0 74 06 5b c3 cc cc cc cc
RSP: 0018:c90003a87b50 EFLAGS: 0282
RAX: 9ede7a61d4cee000 RBX: 888015fb5f30 RCX: 94485303
RDX: dc00 RSI: 

Re: [PATCH 0/2] Match panel hash for overridden mode

2024-02-26 Thread Dmitry Baryshkov
On Sat, 24 Feb 2024 at 00:40, Hsin-Yi Wang  wrote:
>
> This series is a follow up for 1a5e81de180e ("Revert "drm/panel-edp: Add
> auo_b116xa3_mode""). It's found that 2 different AUO panels use the same
> product id. One of them requires an overridden mode, while the other should
> use the mode directly from edid.
>
> Since product id match is no longer sufficient, EDP_PANEL_ENTRY2 is extended
> to check the crc hash of the entire edid base block.

Do you have these EDIDs posted somewhere? Can we use something less
cryptic than hash for matching the panel, e.g. strings from Monitor
Descriptors?

>
> Hsin-Yi Wang (2):
>   drm_edid: Add a function to get EDID base block
>   drm/panel: panel-edp: Match with panel hash for overridden modes
>
>  drivers/gpu/drm/drm_edid.c| 55 +++-
>  drivers/gpu/drm/panel/panel-edp.c | 60 ++-
>  include/drm/drm_edid.h|  3 +-
>  3 files changed, 84 insertions(+), 34 deletions(-)
>
> --
> 2.44.0.rc0.258.g7320e95886-goog
>


-- 
With best wishes
Dmitry


Re: [PATCH 2/2] drm/panel: panel-edp: Match with panel hash for overridden modes

2024-02-26 Thread Doug Anderson
Hi,

On Mon, Feb 26, 2024 at 2:39 PM Hsin-Yi Wang  wrote:
>
> On Mon, Feb 26, 2024 at 2:29 PM Doug Anderson  wrote:
> >
> > Hi,
> >
> > On Fri, Feb 23, 2024 at 2:40 PM Hsin-Yi Wang  wrote:
> > >
> > > It's found that some panels have variants that they share the same panel 
> > > id
> > > although their EDID and names are different. One of the variants requires
> > > using overridden modes to resolve glitching issue as described in commit
> > > 70e0d5550f5c ("drm/panel-edp: Add auo_b116xa3_mode"). Other variants 
> > > should
> > > use the modes parsed from EDID.
> > >
> > > For example, AUO 0x405c B116XAK01.0, it has at least 2 different variants
> > > that EDID and panel name are different, but using the same panel id. One 
> > > of
> > > the variants require using overridden mode. Same case for AUO 0x615c
> > > B116XAN06.1.
> > >
> > > Add such entries and use the hash of the EDID to match the panel needs the
> > > overridden modes.
> >
> > As pointed out in an offline discussion, it's possible that we might
> > want to "ignore" some of these bytes for the purpose of the CRC.
> > Specifically, we might want to ignore:
> > * byte 16 - Week of manufacture
> > * byte 17 - Year of manufacture
> > * byte 127 - Checksum
> >
> > That way if a manufacturer actually is updating those numbers in
> > production we can still have one hash that captures all the panels. I
> > have no idea if manufacturers actually are, but IMO the hash of the
> > rest of the base block should be sufficient to differentiate between
> > different panels anyway. It would be easy to just zero out those 3
> > bytes before computing the CRC.
> >
> > What do you think?
>
> Agreed that we can zero out these fields.

Ah, in (yet another) offline comment, someone also pointed out bytes
12-15 should also be ignored for the CRC. Those are the serial number.

-Doug


Re: [PATCH v3 3/3] drm/i915/guc: Enable Wa_14019159160

2024-02-26 Thread John Harrison

On 2/26/2024 05:25, Nilawar, Badal wrote:

Hi John,

On 04-01-2024 23:35, john.c.harri...@intel.com wrote:

From: John Harrison 

Use the new w/a KLV support to enable a MTL w/a. Note, this w/a is a
super-set of Wa_16019325821, so requires turning that one as well as
setting the new flag for Wa_14019159160 itself.

Signed-off-by: John Harrison 
Reviewed-by: Vinay Belgaumkar 
---
  drivers/gpu/drm/i915/gt/gen8_engine_cs.c  |  3 ++
  drivers/gpu/drm/i915/gt/intel_engine_types.h  |  1 +
  drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h |  7 
  drivers/gpu/drm/i915/gt/uc/intel_guc.c    |  1 +
  drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c    | 34 ++-
  .../gpu/drm/i915/gt/uc/intel_guc_submission.c |  1 +
  6 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c 
b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c

index 9cccd60a5c41d..359b21fb02ab2 100644
--- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
@@ -744,6 +744,7 @@ static u32 *gen12_emit_preempt_busywait(struct 
i915_request *rq, u32 *cs)

    /* Wa_14014475959:dg2 */
  /* Wa_16019325821 */
+/* Wa_14019159160 */
  #define HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET    0x540
  static u32 hold_switchout_semaphore_offset(struct i915_request *rq)
  {
@@ -753,6 +754,7 @@ static u32 hold_switchout_semaphore_offset(struct 
i915_request *rq)

    /* Wa_14014475959:dg2 */
  /* Wa_16019325821 */
+/* Wa_14019159160 */
  static u32 *hold_switchout_emit_wa_busywait(struct i915_request 
*rq, u32 *cs)

  {
  int i;
@@ -793,6 +795,7 @@ gen12_emit_fini_breadcrumb_tail(struct 
i915_request *rq, u32 *cs)

    /* Wa_14014475959:dg2 */
  /* Wa_16019325821 */
+    /* Wa_14019159160 */
  if (intel_engine_uses_wa_hold_switchout(rq->engine))
  cs = hold_switchout_emit_wa_busywait(rq, cs);
  diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h 
b/drivers/gpu/drm/i915/gt/intel_engine_types.h

index b519812ba120d..ba55c059063db 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -697,6 +697,7 @@ intel_engine_has_relative_mmio(const struct 
intel_engine_cs * const engine)

    /* Wa_14014475959:dg2 */
  /* Wa_16019325821 */
+/* Wa_14019159160 */
  static inline bool
  intel_engine_uses_wa_hold_switchout(struct intel_engine_cs *engine)
  {
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h 
b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h

index 58012edd4eb0e..bebf28e3c4794 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h
@@ -101,4 +101,11 @@ enum {
  GUC_CONTEXT_POLICIES_KLV_NUM_IDS = 5,
  };
  +/*
+ * Workaround keys:
+ */
+enum {
+    GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE    = 0x9001,
+};
+
  #endif /* _ABI_GUC_KLVS_ABI_H */
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.c

index d5c856be31491..db3cb628f40dc 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -295,6 +295,7 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc)
  flags |= GUC_WA_HOLD_CCS_SWITCHOUT;
    /* Wa_16019325821 */
+    /* Wa_14019159160 */
  if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71)))
  flags |= GUC_WA_RCS_CCS_SWITCHOUT;
  diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c

index 6af3fa8b92e34..68d9e277eca8b 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
@@ -815,6 +815,25 @@ guc_capture_prep_lists(struct intel_guc *guc)
  return PAGE_ALIGN(total_size);
  }
  +/* Wa_14019159160 */
+static u32 guc_waklv_ra_mode(struct intel_guc *guc, u32 offset, u32 
remain)

+{

How about making this function generic by passing KLV id as arg?
At this point, there is only one KLV supported. So there is no advantage 
to making the code more complex.


The next patch in the series (not yet posted because this one was not 
supposed to be taking so long to get through CI and merged!) adds 
support for another KLV which is similarly zero length. At that point, 
the helper function is updated to become more generic.


John.


+    u32 size;
+    u32 klv_entry[] = {
+    /* 16:16 key/length */
+    FIELD_PREP(GUC_KLV_0_KEY, 
GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE) |

+    FIELD_PREP(GUC_KLV_0_LEN, 0),
+    /* 0 dwords data */
+    };
+
+    size = sizeof(klv_entry);
+    GEM_BUG_ON(remain < size);
+
+    iosys_map_memcpy_to(>ads_map, offset, klv_entry, size);
Otherwise preparing and adding klv entry can be wrapped in generic 
function.


Regards,
Badal

+
+    return size;
+}
+
  static void guc_waklv_init(struct intel_guc *guc)
  {
  struct intel_gt *gt = guc_to_gt(guc);
@@ -830,15 +849,12 @@ static void guc_waklv_init(struct intel_guc *guc)
  offset = guc_ads_waklv_offset(guc);
  remain 

Re: [PATCH] net: ethernet: ti: am65-cpsw: Add minimal XDP support

2024-02-26 Thread Andrew Lunn
> +static struct sk_buff *am65_cpsw_alloc_skb(struct net_device *ndev, unsigned 
> int len)
> +{
> + struct page *page;
> + struct sk_buff *skb;
> +
> + page = dev_alloc_pages(0);

You are likely to get better performance if you use the page_pool.

When FEC added XDP support, the first set of changes was to make use
of page_pool. That improved the drivers performance. Then XDP was
added on top. Maybe you can follow that pattern.

  Andrew


Re: [PATCH v2 resend 0/4] of: replace of_graph_get_next_endpoint()

2024-02-26 Thread Kuninori Morimoto


Hi Rob

> This is resend v2 of replace of_graph_get_next_endpoint()
> 
> We should get rid of or minimize of_graph_get_next_endpoint() in
> its current form. In general, drivers should be asking for a specific 
> port number because their function is fixed in the binding.
> 
>   https://lore.kernel.org/r/20240131184347.ga1906672-r...@kernel.org
> 
> This patch-set replace of_graph_get_next_endpoint() by
> of_graph_get_endpoint_by_regs(). There are still next_endpoint()
> after this patch-set, but it will be replaced by
> for_each_endpoint_of_node() in next patch-set (A)
> 
> [*] this patch-set
> [o] done
> 
>   [o] tidyup of_graph_get_endpoint_count()
>   [*] replace endpoint func - use endpoint_by_regs()
> (A)   [ ] replace endpoint func - use for_each()
>   [ ] rename endpoint func to device_endpoint
>   [ ] add new port function
>   [ ] add new endpont function
>   [ ] remove of_graph_get_next_device_endpoint()
> 
> v1 -> v2
>   - add Reviewed-by from Launrent
>   - use by_regs(xx, -1, -1) for some devices
>   - add extra explain for drm_of_get_dsi_bus()
>   - add FIXME and Link on adv7604.c
>   - based on latest of branch
> 
> Kuninori Morimoto (4):
>   gpu: drm: replace of_graph_get_next_endpoint()
>   media: i2c: replace of_graph_get_next_endpoint()
>   media: platform: replace of_graph_get_next_endpoint()
>   video: fbdev: replace of_graph_get_next_endpoint()

I wonder who should handle this patch-set ??
I'm posting these as part of "of patch-set" (= to Rob)
but does these should be handled by each driver maintainer ?
(I believe all maintainers are listed on To)

Thank you for your help !!

Best regards
---
Renesas Electronics
Ph.D. Kuninori Morimoto


Re: [PATCH] drm/msm/dp: fix runtime_pm handling in dp_wait_hpd_asserted

2024-02-26 Thread Abhinav Kumar




On 2/26/2024 2:34 PM, Dmitry Baryshkov wrote:

The function dp_wait_hpd_asserted() uses pm_runtime_get_sync() and
doesn't care about the return value. Potentially this can lead to
unclocked access if for some reason resuming of the DP controller fails.

Change the function to use pm_runtime_resume_and_get() and return an
error if resume fails.

Fixes: e2969ee30252 ("drm/msm/dp: move of_dp_aux_populate_bus() to eDP probe()")
Signed-off-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/msm/dp/dp_aux.c | 5 -
  1 file changed, 4 insertions(+), 1 deletion(-)



Reviewed-by: Abhinav Kumar 


Re: [PATCH 2/2] drm/panel: panel-edp: Match with panel hash for overridden modes

2024-02-26 Thread Hsin-Yi Wang
On Mon, Feb 26, 2024 at 2:29 PM Doug Anderson  wrote:
>
> Hi,
>
> On Fri, Feb 23, 2024 at 2:40 PM Hsin-Yi Wang  wrote:
> >
> > It's found that some panels have variants that they share the same panel id
> > although their EDID and names are different. One of the variants requires
> > using overridden modes to resolve glitching issue as described in commit
> > 70e0d5550f5c ("drm/panel-edp: Add auo_b116xa3_mode"). Other variants should
> > use the modes parsed from EDID.
> >
> > For example, AUO 0x405c B116XAK01.0, it has at least 2 different variants
> > that EDID and panel name are different, but using the same panel id. One of
> > the variants require using overridden mode. Same case for AUO 0x615c
> > B116XAN06.1.
> >
> > Add such entries and use the hash of the EDID to match the panel needs the
> > overridden modes.
>
> As pointed out in an offline discussion, it's possible that we might
> want to "ignore" some of these bytes for the purpose of the CRC.
> Specifically, we might want to ignore:
> * byte 16 - Week of manufacture
> * byte 17 - Year of manufacture
> * byte 127 - Checksum
>
> That way if a manufacturer actually is updating those numbers in
> production we can still have one hash that captures all the panels. I
> have no idea if manufacturers actually are, but IMO the hash of the
> rest of the base block should be sufficient to differentiate between
> different panels anyway. It would be easy to just zero out those 3
> bytes before computing the CRC.
>
> What do you think?

Agreed that we can zero out these fields.

>
>
> > @@ -758,13 +762,13 @@ static void panel_edp_parse_panel_timing_node(struct 
> > device *dev,
> > dev_err(dev, "Reject override mode: No display_timing 
> > found\n");
> >  }
> >
> > -static const struct edp_panel_entry *find_edp_panel(u32 panel_id);
> > +static const struct edp_panel_entry *find_edp_panel(u32 panel_id, u32 
> > panel_hash);
> >
> >  static int generic_edp_panel_probe(struct device *dev, struct panel_edp 
> > *panel)
> >  {
> > struct panel_desc *desc;
> > void *base_block;
> > -   u32 panel_id;
> > +   u32 panel_id, panel_hash;
> > char vend[4];
> > u16 product_id;
> > u32 reliable_ms = 0;
> > @@ -796,15 +800,17 @@ static int generic_edp_panel_probe(struct device 
> > *dev, struct panel_edp *panel)
> > base_block = drm_edid_get_base_block(panel->ddc);
> > if (base_block) {
> > panel_id = drm_edid_get_panel_id(base_block);
> > +   panel_hash = crc32_le(~0, base_block, EDID_LENGTH) ^ 
> > 0x;
>
> Any reason you need to XOR with 0x?
>
To be consistent with the crc32[1] command. It's more convenient to be
able to verify it with userspace tools.

[1] https://www.commandlinux.com/man-page/man1/crc32.1.html

>
> > @@ -2077,13 +2098,32 @@ static const struct edp_panel_entry edp_panels[] = {
> > { /* sentinal */ }
> >  };
> >
> > -static const struct edp_panel_entry *find_edp_panel(u32 panel_id)
> > +/*
> > + * Similar to edp_panels, this table lists panel variants that require 
> > using
> > + * overridden modes but have the same panel id as one of the entries in 
> > edp_panels.
> > + *
> > + * Sort first by vendor, then by product ID.
>
> Add ", then by hash" just in case we need it.
>
>
> > +static const struct edp_panel_entry *find_edp_panel(u32 panel_id, u32 
> > panel_hash)
> >  {
> > const struct edp_panel_entry *panel;
> >
> > -   if (!panel_id)
> > +   if (!panel_id || !panel_hash)
> > return NULL;
>
> IMO just remove the check above. Not sure why it was there in the
> first place. Maybe I had it from some older version of the code?
> Callers shouldn't be calling us with a panel ID / hash of 0 anyway,
> and if they do they'll go through the loop and return NULL anyway.
>

Sure.

>
>
> -Doug


[PATCH] drm/msm/dp: fix runtime_pm handling in dp_wait_hpd_asserted

2024-02-26 Thread Dmitry Baryshkov
The function dp_wait_hpd_asserted() uses pm_runtime_get_sync() and
doesn't care about the return value. Potentially this can lead to
unclocked access if for some reason resuming of the DP controller fails.

Change the function to use pm_runtime_resume_and_get() and return an
error if resume fails.

Fixes: e2969ee30252 ("drm/msm/dp: move of_dp_aux_populate_bus() to eDP probe()")
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_aux.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index 03f4951c49f4..1a264e7deb90 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -509,7 +509,10 @@ static int dp_wait_hpd_asserted(struct drm_dp_aux *dp_aux,
 
aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
 
-   pm_runtime_get_sync(aux->dev);
+   ret = pm_runtime_resume_and_get(aux->dev);
+   if (ret)
+   return ret;
+
ret = dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog);
pm_runtime_put_sync(aux->dev);
 
-- 
2.39.2



Re: [PATCH 2/2] drm/panel: panel-edp: Match with panel hash for overridden modes

2024-02-26 Thread Doug Anderson
Hi,

On Fri, Feb 23, 2024 at 2:40 PM Hsin-Yi Wang  wrote:
>
> It's found that some panels have variants that they share the same panel id
> although their EDID and names are different. One of the variants requires
> using overridden modes to resolve glitching issue as described in commit
> 70e0d5550f5c ("drm/panel-edp: Add auo_b116xa3_mode"). Other variants should
> use the modes parsed from EDID.
>
> For example, AUO 0x405c B116XAK01.0, it has at least 2 different variants
> that EDID and panel name are different, but using the same panel id. One of
> the variants require using overridden mode. Same case for AUO 0x615c
> B116XAN06.1.
>
> Add such entries and use the hash of the EDID to match the panel needs the
> overridden modes.

As pointed out in an offline discussion, it's possible that we might
want to "ignore" some of these bytes for the purpose of the CRC.
Specifically, we might want to ignore:
* byte 16 - Week of manufacture
* byte 17 - Year of manufacture
* byte 127 - Checksum

That way if a manufacturer actually is updating those numbers in
production we can still have one hash that captures all the panels. I
have no idea if manufacturers actually are, but IMO the hash of the
rest of the base block should be sufficient to differentiate between
different panels anyway. It would be easy to just zero out those 3
bytes before computing the CRC.

What do you think?


> @@ -758,13 +762,13 @@ static void panel_edp_parse_panel_timing_node(struct 
> device *dev,
> dev_err(dev, "Reject override mode: No display_timing 
> found\n");
>  }
>
> -static const struct edp_panel_entry *find_edp_panel(u32 panel_id);
> +static const struct edp_panel_entry *find_edp_panel(u32 panel_id, u32 
> panel_hash);
>
>  static int generic_edp_panel_probe(struct device *dev, struct panel_edp 
> *panel)
>  {
> struct panel_desc *desc;
> void *base_block;
> -   u32 panel_id;
> +   u32 panel_id, panel_hash;
> char vend[4];
> u16 product_id;
> u32 reliable_ms = 0;
> @@ -796,15 +800,17 @@ static int generic_edp_panel_probe(struct device *dev, 
> struct panel_edp *panel)
> base_block = drm_edid_get_base_block(panel->ddc);
> if (base_block) {
> panel_id = drm_edid_get_panel_id(base_block);
> +   panel_hash = crc32_le(~0, base_block, EDID_LENGTH) ^ 
> 0x;

Any reason you need to XOR with 0x?


> @@ -2077,13 +2098,32 @@ static const struct edp_panel_entry edp_panels[] = {
> { /* sentinal */ }
>  };
>
> -static const struct edp_panel_entry *find_edp_panel(u32 panel_id)
> +/*
> + * Similar to edp_panels, this table lists panel variants that require using
> + * overridden modes but have the same panel id as one of the entries in 
> edp_panels.
> + *
> + * Sort first by vendor, then by product ID.

Add ", then by hash" just in case we need it.


> +static const struct edp_panel_entry *find_edp_panel(u32 panel_id, u32 
> panel_hash)
>  {
> const struct edp_panel_entry *panel;
>
> -   if (!panel_id)
> +   if (!panel_id || !panel_hash)
> return NULL;

IMO just remove the check above. Not sure why it was there in the
first place. Maybe I had it from some older version of the code?
Callers shouldn't be calling us with a panel ID / hash of 0 anyway,
and if they do they'll go through the loop and return NULL anyway.



-Doug


Re: [PATCH 1/2] drm_edid: Add a function to get EDID base block

2024-02-26 Thread Doug Anderson
Hi,

On Fri, Feb 23, 2024 at 2:40 PM Hsin-Yi Wang  wrote:
>
> @@ -2770,58 +2770,63 @@ static u32 edid_extract_panel_id(const struct edid 
> *edid)
>  }
>
>  /**
> - * drm_edid_get_panel_id - Get a panel's ID through DDC
> - * @adapter: I2C adapter to use for DDC
> + * drm_edid_get_panel_id - Get a panel's ID from EDID base block
> + * @base_bock: EDID base block that contains panel ID.

s/base_bock/base_block, as identified by:

scripts/kernel-doc -v drivers/gpu/drm/drm_edid.c | less 2>&1

drivers/gpu/drm/drm_edid.c:2787: warning: Function parameter or struct
member 'base_block' not described in 'drm_edid_get_panel_id'
drivers/gpu/drm/drm_edid.c:2787: warning: Excess function parameter
'base_bock' description in 'drm_edid_get_panel_id'


>   *
> - * This function reads the first block of the EDID of a panel and (assuming
> + * This function uses the first block of the EDID of a panel and (assuming
>   * that the EDID is valid) extracts the ID out of it. The ID is a 32-bit 
> value
>   * (16 bits of manufacturer ID and 16 bits of per-manufacturer ID) that's
>   * supposed to be different for each different modem of panel.
>   *
> + * Return: A 32-bit ID that should be different for each make/model of panel.
> + * See the functions drm_edid_encode_panel_id() and
> + * drm_edid_decode_panel_id() for some details on the structure of 
> this
> + * ID.
> + */
> +u32 drm_edid_get_panel_id(void *base_block)
> +{
> +   return edid_extract_panel_id(base_block);
> +}
> +EXPORT_SYMBOL(drm_edid_get_panel_id);
> +
> +/**
> + * drm_edid_get_base_block - Get a panel's EDID base block
> + * @adapter: I2C adapter to use for DDC
> + *
> + * This function returns the first block of the EDID of a panel.
> + *
>   * This function is intended to be used during early probing on devices where
>   * more than one panel might be present. Because of its intended use it must
> - * assume that the EDID of the panel is correct, at least as far as the ID
> - * is concerned (in other words, we don't process any overrides here).
> + * assume that the EDID of the panel is correct, at least as far as the base
> + * block is concerned (in other words, we don't process any overrides here).
>   *
>   * NOTE: it's expected that this function and drm_do_get_edid() will both
>   * be read the EDID, but there is no caching between them. Since we're only
>   * reading the first block, hopefully this extra overhead won't be too big.
>   *
> - * Return: A 32-bit ID that should be different for each make/model of panel.
> - * See the functions drm_edid_encode_panel_id() and
> - * drm_edid_decode_panel_id() for some details on the structure of 
> this
> - * ID.
> + * Caller should free the base block after use.

Don't you need a "Return:" clause here to document what you're returning?


Other than the kernel-doc nits, this looks fine to me.

Reviewed-by: Douglas Anderson 

It'll probably need at least an Ack from someone else in the DRM
community before it can land, though, since this is touching a core
file.


-Doug


Re: [PATCH] drm/dp: Don't attempt AUX transfers when eDP panels are not powered

2024-02-26 Thread Steev Klimaszewski
On Fri, Feb 16, 2024 at 9:30 AM Doug Anderson  wrote:
>
> Hi,
>
> On Fri, Feb 16, 2024 at 12:21 AM Javier Martinez Canillas
>  wrote:
> >
> > > The kernel tree we landed on was the v5.15 tree, which is currently
> > > serving all Qualcomm sc7180-based Chromebooks, all Mediatek 8173
> > > Chromebooks and all Mediatek 8186 Chromebooks. There are also a pile
> > > of x86 Chromebooks running our v5.15 kernel. This code shouldn't
> > > affect them because (unless I'm mistaken) they don't use the two
> > > affected panel drivers. In any case, I haven't heard any screams from
> > > them either. Given my landing plans of "the week of the 26th", this
> > > still gives another 1.5 weeks for any screams to reach my ears.
> > >
> > > ...or are you looking for non-ChromeOS test reports? I'm not sure how
> > > to encourage those. I suppose sometimes folks at Red Hat end up
> > > stumbling over similar panel problems to those of us in ChromeOS.
> > > Maybe +Javier would be interested in providing a Tested-by?
> > >
> >
> > I do have a SC7180 based HP X2 Chromebook and could test your patch (not
> > today but I could do it early next week), although I haven't followed so
> > if you could please let me know what exactly do you want me to verify.
> >
> > AFAIU the problem is that the fwupd daemon tries to scan DP busses even if
> > the panel is turned off and that's what takes a lot of time (due retries),
> > and your patch makes the driver to bail out immediately ? If that's the
> > case, I guess that just starting fwupd daemon with an without your patch
> > while the panel is turned off could be a good test ?
>
> Sorry! I wasn't trying to sign you up for extra work. I'm not
> convinced that any extra verification on a Chromebook is all that
> valuable since that's pretty covered by the fact that we've already
> pushed this patch out to real users on Chromebooks. I think Neil was
> hoping for some confirmation that my patch didn't break someone else's
> hardware. I think maybe good enough is if you have some type of
> hardware that uses eDP and that you could verify that my patch does
> break anything about it?
>
> I'm not aware of anyone with extensive DP AUX character device usage.
> I guess I thought of Javier because I remembered him at least also
> using fwupd and some of the fwupd plugins try to talk to DP things
> over the DP AUX character device.
>
> If someone is really in a testing mood and wanted to stress the char
> device, I guess something simple like "hexdump -C /dev/drm_dp_aux*"
> for whatever eDP AUX is associated with eDP would at least do some
> reading. You could stress turning the display on and off while doing
> that with and without my patch. Presumably it will be better (error
> out more quickly) with my patch.
>
> If you wanted to stress the i2c path, you could do something like this
> (the grep assumes you're using ti-sn65dsi86 as your eDP bridge chip,
> but hopefully easy to adjust):
>
> bus=$(i2cdetect -l | grep sn65 | sed 's/i2c-\([0-9]*\).*$/\1/')
> i2cdump ${bus} 0x50 i
>
> That should dump your EDID. Again it should error out quickly when the
> panel is off after my patch but should start working again when the
> panel is on.
>
>
> Hmmm, thinking about all the above, I guess there is one case that
> _could_ be broken by my patch. I really hope not, though. If someone
> has a panel that's on an always-on rail or on a shared rail with some
> other device (like the touchscreen) that's keeping the panel power on
> then without my patch it would be possible to do DP AUX transactions
> even when the panel was "off" from Linux's point of view. It would
> have worked mostly due to luck, but now luck will run out and it will
> stop working. I really hope nobody has userspace that is relying on
> this, but I suppose it's always possible that somewhere, someone's
> userspace is. If you are or know of someone who is then please shout.
>
> -Doug

Tested on my Thinkpad X13s, with display on, I get the did when
hexdumping /dev/drm_dp_aux2, with display off I get device/resource
busy.
Tested-by: Steev Klimaszewski 


Re: drm-misc migration to Gitlab server

2024-02-26 Thread Stephen Rothwell
Hi Daniel,

On Mon, 26 Feb 2024 15:50:10 +0100 Daniel Vetter  wrote:
>
> > git://git.freedesktop.org/git/drm/drm.git#topic/drm-ci  
> 
> This one you can drop right away, it's all merged, apologies for not
> telling you earlier.

Thanks, removed now.

-- 
Cheers,
Stephen Rothwell


pgpd6KgfsRTmt.pgp
Description: OpenPGP digital signature


Re: [PATCH 3/3] drm/panel: simple: add CMT430B19N00 LCD panel support

2024-02-26 Thread Jessica Zhang




On 2/23/2024 5:45 AM, Jérémie Dautheribes wrote:

Add support for Crystal Clear Technology CMT430B19N00 4.3" 480x272
TFT-LCD panel.

Signed-off-by: Jérémie Dautheribes 


Hi Jérémie,

Reviewed-by: Jessica Zhang 

Thanks,

Jessica Zhang


---
  drivers/gpu/drm/panel/panel-simple.c | 29 
  1 file changed, 29 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index 20e3df1c59d4..b940220f56e2 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -1457,6 +1457,32 @@ static const struct panel_desc boe_hv070wsa = {
.connector_type = DRM_MODE_CONNECTOR_LVDS,
  };
  
+static const struct drm_display_mode cct_cmt430b19n00_mode = {

+   .clock = 9000,
+   .hdisplay = 480,
+   .hsync_start = 480 + 43,
+   .hsync_end = 480 + 43 + 8,
+   .htotal = 480 + 43 + 8 + 4,
+   .vdisplay = 272,
+   .vsync_start = 272 + 12,
+   .vsync_end = 272 + 12 + 8,
+   .vtotal = 272 + 12 + 8 + 4,
+   .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+};
+
+static const struct panel_desc cct_cmt430b19n00 = {
+   .modes = _cmt430b19n00_mode,
+   .num_modes = 1,
+   .bpc = 8,
+   .size = {
+   .width = 95,
+   .height = 53,
+   },
+   .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+   .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE,
+   .connector_type = DRM_MODE_CONNECTOR_DPI,
+};
+
  static const struct drm_display_mode cdtech_s043wq26h_ct7_mode = {
.clock = 9000,
.hdisplay = 480,
@@ -4402,6 +4428,9 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "boe,hv070wsa-100",
.data = _hv070wsa
+   }, {
+   .compatible = "cct,cmt430b19n00",
+   .data = _cmt430b19n00,
}, {
.compatible = "cdtech,s043wq26h-ct7",
.data = _s043wq26h_ct7,
--
2.34.1



Re: [PATCH v2 1/2] drm: panel: st7701: Add Hardkernel ODROID-GO Ultra panel support

2024-02-26 Thread Jessica Zhang




On 2/22/2024 9:47 AM, Adam Green wrote:

On 22/02/2024 17:14, Jessica Zhang wrote:

Hi Adam,

Just wondering, why the change to 120 here?

Thanks,

Jessica Zhang


Hi,

The 120ms is taken from the datasheet specification for the controller 
as maximum time it takes for the display to reset,


Got it. Was the shorter sleep time breaking the display and is it 
required for the new panel to work?


Thanks,

Jessica Zhang



Kind regards,

Adam


[PATCH] drm/bridge: anx7625: Don't log an error when DSI host can't be found

2024-02-26 Thread Nícolas F . R . A . Prado
Given that failing to find a DSI host causes the driver to defer probe,
make use of dev_err_probe() to log the reason. This makes the defer
probe reason available and avoids alerting userspace about something
that is not necessarily an error.

Fixes: 269332997a16 ("drm/bridge: anx7625: Return -EPROBE_DEFER if the dsi host 
was not found")
Signed-off-by: Nícolas F. R. A. Prado 
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 29d91493b101..4ee5614a2623 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -2076,10 +2076,8 @@ static int anx7625_setup_dsi_device(struct anx7625_data 
*ctx)
};
 
host = of_find_mipi_dsi_host_by_node(ctx->pdata.mipi_host_node);
-   if (!host) {
-   DRM_DEV_ERROR(dev, "fail to find dsi host.\n");
-   return -EPROBE_DEFER;
-   }
+   if (!host)
+   return dev_err_probe(dev, -EPROBE_DEFER, "fail to find dsi 
host.\n");
 
dsi = devm_mipi_dsi_device_register_full(dev, host, );
if (IS_ERR(dsi)) {

---
base-commit: 2ae0a045e6814c8c1d676d6153c605a65746aa29
change-id: 20240226-anx7625-defer-log-no-dsi-host-c3f9ccbcb287

Best regards,
-- 
Nícolas F. R. A. Prado 



[RFC PATCH v4 32/42] drm/amd/display: Add support for sRGB Inverse EOTF in SHAPER block

2024-02-26 Thread Harry Wentland
From: Alex Hung 

Expose a 2nd curve colorop with support for
DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF and program HW to
perform the sRGB Inverse EOTF on the shaper block
when the colorop is not in bypass.

With this change the follow IGT tests pass:
kms_colorop --run plane-XR30-XR30-srgb_inv_eotf
kms_colorop --run plane-XR30-XR30-srgb_eotf-srgb_inv_eotf

The color pipeline now consists of the following colorops:
1. 1D curve colorop w/ sRGB EOTF support
2. 1D curve colorop w/ sRGB Inverse EOTF support

Signed-off-by: Alex Hung 
Signed-off-by: Harry Wentland 
Co-developed-by: Harry Wentland 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 76 +++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 20 -
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.h |  1 +
 3 files changed, 96 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 3ec759934669..8788cfd26abd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1203,6 +1203,70 @@ __set_dm_plane_colorop_degamma(struct drm_plane_state 
*plane_state,
return __set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state);
 }
 
+static int
+__set_colorop_in_shaper_1d_curve(struct dc_plane_state *dc_plane_state,
+  struct drm_colorop_state *colorop_state)
+{
+   struct dc_transfer_func *tf = dc_plane_state->in_shaper_func;
+   struct drm_colorop *colorop = colorop_state->colorop;
+   struct drm_device *drm = colorop->dev;
+   const struct drm_color_lut *shaper_lut;
+   uint32_t shaper_size;
+
+   if (colorop->type != DRM_COLOROP_1D_CURVE &&
+   colorop_state->curve_1d_type != DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF)
+   return -EINVAL;
+
+   if (colorop_state->bypass) {
+   tf->type = TF_TYPE_BYPASS;
+   tf->tf = TRANSFER_FUNCTION_LINEAR;
+   return 0;
+   }
+
+   drm_dbg(drm, "Shaper colorop with ID: %d\n", colorop->base.id);
+
+   if (colorop->type == DRM_COLOROP_1D_CURVE) {
+   tf->type = TF_TYPE_DISTRIBUTED_POINTS;
+   tf->tf = 
amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
+   tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
+   return __set_output_tf(tf, shaper_lut, shaper_size, false);
+   }
+
+   return -EINVAL;
+}
+
+static int
+__set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
+ struct dc_plane_state *dc_plane_state,
+ struct drm_colorop *colorop)
+{
+   struct drm_colorop *old_colorop;
+   struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+   struct drm_atomic_state *state = plane_state->state;
+   int i = 0;
+
+   old_colorop = colorop;
+
+   /* 2nd op: 1d curve - shaper */
+   for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+   if (new_colorop_state->colorop == old_colorop &&
+   new_colorop_state->curve_1d_type == 
DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF) {
+   colorop_state = new_colorop_state;
+   break;
+   }
+
+   if (new_colorop_state->colorop == old_colorop) {
+   colorop_state = new_colorop_state;
+   break;
+   }
+   }
+
+   if (!colorop_state)
+   return -EINVAL;
+
+   return __set_colorop_in_shaper_1d_curve(dc_plane_state, colorop_state);
+}
+
 static int
 amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
 struct dc_plane_state *dc_plane_state)
@@ -1258,6 +1322,7 @@ amdgpu_dm_plane_set_colorop_properties(struct 
drm_plane_state *plane_state,
   struct dc_plane_state *dc_plane_state)
 {
struct drm_colorop *colorop = plane_state->color_pipeline;
+   struct drm_device *dev = plane_state->plane->dev;
int ret;
 
/* 1D Curve - DEGAM TF */
@@ -1269,6 +1334,17 @@ amdgpu_dm_plane_set_colorop_properties(struct 
drm_plane_state *plane_state,
if (ret)
return ret;
 
+   /* 1D Curve - SHAPER TF */
+   colorop = colorop->next;
+   if (!colorop) {
+   drm_dbg(dev, "no Shaper TF colorop found\n");
+   return -EINVAL;
+   }
+
+   ret = __set_dm_plane_colorop_shaper(plane_state, dc_plane_state, 
colorop);
+   if (ret)
+   return ret;
+
return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index e8b7fc8bb0f1..0d1626abf577 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -34,9 +34,12 @@
 const u64 

[RFC PATCH v4 31/42] drm/amd/display: Add support for sRGB EOTF in DEGAM block

2024-02-26 Thread Harry Wentland
From: Alex Hung 

Expose one 1D curve colorop with support for
DRM_COLOROP_1D_CURVE_SRGB_EOTF and program HW to perform
the sRGB transform when the colorop is not in bypass.

With this change the following IGT test passes:
kms_colorop --run plane-XR30-XR30-srgb_eotf

The color pipeline now consists of a single colorop:
1. 1D curve colorop w/ sRGB EOTF

Signed-off-by: Alex Hung 
Signed-off-by: Harry Wentland 
Co-developed-by: Harry Wentland 
---
 .../gpu/drm/amd/display/amdgpu_dm/Makefile|  3 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 88 +++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 58 
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.h | 34 +++
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 10 +++
 5 files changed, 192 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile 
b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
index ab2a97e354da..46158d67ab12 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
@@ -38,7 +38,8 @@ AMDGPUDM = \
amdgpu_dm_pp_smu.o \
amdgpu_dm_psr.o \
amdgpu_dm_replay.o \
-   amdgpu_dm_wb.o
+   amdgpu_dm_wb.o \
+   amdgpu_dm_colorop.o
 
 ifdef CONFIG_DRM_AMD_DC_FP
 AMDGPUDM += dc_fpu.o
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 9b527bffe11a..3ec759934669 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -668,6 +668,19 @@ amdgpu_tf_to_dc_tf(enum amdgpu_transfer_function tf)
}
 }
 
+static enum dc_transfer_func_predefined
+amdgpu_colorop_tf_to_dc_tf(enum drm_colorop_curve_1d_type tf)
+{
+   switch (tf)
+   {
+   case DRM_COLOROP_1D_CURVE_SRGB_EOTF:
+   case DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF:
+   return TRANSFER_FUNCTION_SRGB;
+   default:
+   return TRANSFER_FUNCTION_LINEAR;;
+   }
+}
+
 static void __to_dc_lut3d_color(struct dc_rgb *rgb,
const struct drm_color_lut lut,
int bit_precision)
@@ -1137,6 +1150,59 @@ __set_dm_plane_degamma(struct drm_plane_state 
*plane_state,
return 0;
 }
 
+static int
+__set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
+  struct drm_colorop_state *colorop_state)
+{
+   struct dc_transfer_func *tf = dc_plane_state->in_transfer_func;
+   struct drm_colorop *colorop = colorop_state->colorop;
+   struct drm_device *drm = colorop->dev;
+
+   if (colorop->type != DRM_COLOROP_1D_CURVE &&
+   colorop_state->curve_1d_type != DRM_COLOROP_1D_CURVE_SRGB_EOTF)
+   return -EINVAL;
+
+   if (colorop_state->bypass) {
+   tf->type = TF_TYPE_BYPASS;
+   tf->tf = TRANSFER_FUNCTION_LINEAR;
+   return 0;
+   }
+
+   drm_dbg(drm, "Degamma colorop with ID: %d\n", colorop->base.id);
+
+   tf->type = TF_TYPE_PREDEFINED;
+   tf->tf = amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
+
+   return 0;
+}
+
+static int
+__set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
+  struct dc_plane_state *dc_plane_state,
+  struct drm_colorop *colorop)
+{
+   struct drm_colorop *old_colorop;
+   struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+   struct drm_atomic_state *state = plane_state->state;
+   int i = 0;
+
+   old_colorop = colorop;
+
+   /* 1st op: 1d curve - degamma */
+   for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+   if (new_colorop_state->colorop == old_colorop &&
+   new_colorop_state->curve_1d_type == 
DRM_COLOROP_1D_CURVE_SRGB_EOTF) {
+   colorop_state = new_colorop_state;
+   break;
+   }
+   }
+
+   if (!colorop_state)
+   return -EINVAL;
+
+   return __set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state);
+}
+
 static int
 amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
 struct dc_plane_state *dc_plane_state)
@@ -1187,6 +1253,25 @@ amdgpu_dm_plane_set_color_properties(struct 
drm_plane_state *plane_state,
return 0;
 }
 
+static int
+amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
+  struct dc_plane_state *dc_plane_state)
+{
+   struct drm_colorop *colorop = plane_state->color_pipeline;
+   int ret;
+
+   /* 1D Curve - DEGAM TF */
+   if (!colorop) {
+   return -EINVAL;
+   }
+
+   ret = 

[RFC PATCH v4 41/42] drm/colorop: Add mutliplier type

2024-02-26 Thread Harry Wentland
From: Alex Hung 

This introduces a new drm_colorop_type: DRM_COLOROP_MULTIPLIER.

It's a simple multiplier to all pixel values. The value is
specified via a S31.32 fixed point provided via the
"MULTIPLIER" property.

Signed-off-by: Alex Hung 
---
 drivers/gpu/drm/drm_atomic.c  |  3 +++
 drivers/gpu/drm/drm_atomic_uapi.c |  4 
 drivers/gpu/drm/drm_colorop.c | 29 +++--
 include/drm/drm_colorop.h | 16 
 include/uapi/drm/drm_mode.h   |  1 +
 5 files changed, 51 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index f7d51839ca03..af0b6338a55c 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -806,6 +806,9 @@ static void drm_atomic_colorop_print_state(struct 
drm_printer *p,
case DRM_COLOROP_CTM_3X4:
drm_printf(p, "\tdata blob id=%d\n", state->data ? 
state->data->base.id : 0);
break;
+   case DRM_COLOROP_MULTIPLIER:
+   drm_printf(p, "\tmultiplier=%u\n", state->multiplier);
+   break;
default:
break;
}
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index 6bfe857720cd..b4ecda563728 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -727,6 +727,8 @@ static int drm_atomic_colorop_set_property(struct 
drm_colorop *colorop,
state->bypass = val;
} else if (property == colorop->curve_1d_type_property) {
state->curve_1d_type = val;
+   } else if (property == colorop->multiplier_property) {
+   state->multiplier = val;
} else if (property == colorop->data_property) {
return drm_atomic_color_set_data_property(colorop,
state, property, val);
@@ -752,6 +754,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
*val = state->bypass;
} else if (property == colorop->curve_1d_type_property) {
*val = state->curve_1d_type;
+   } else if (property == colorop->multiplier_property) {
+   *val = state->multiplier;
} else if (property == colorop->size_property) {
*val = state->size;
} else if (property == colorop->data_property) {
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 4452eaeeb242..c6cdd743de51 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -35,7 +35,8 @@
 static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
{ DRM_COLOROP_1D_CURVE, "1D Curve" },
{ DRM_COLOROP_1D_LUT, "1D Curve Custom LUT" },
-   { DRM_COLOROP_CTM_3X4, "3x4 Matrix"}
+   { DRM_COLOROP_CTM_3X4, "3x4 Matrix"},
+   { DRM_COLOROP_MULTIPLIER, "Multiplier"},
 };
 
 static const char * const colorop_curve_1d_type_names[] = {
@@ -231,6 +232,29 @@ int drm_colorop_ctm_3x4_init(struct drm_device *dev, 
struct drm_colorop *colorop
 }
 EXPORT_SYMBOL(drm_colorop_ctm_3x4_init);
 
+int drm_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop,
+ struct drm_plane *plane)
+{
+   struct drm_property *prop;
+   int ret;
+
+   ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_MULTIPLIER);
+   if (ret)
+   return ret;
+
+   prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, 
"MULTIPLIER", 0, U64_MAX);
+   if (!prop)
+   return -ENOMEM;
+
+   colorop->multiplier_property = prop;
+   drm_object_attach_property(>base, 
colorop->multiplier_property, 0);
+
+   drm_colorop_reset(colorop);
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_colorop_mult_init);
+
 static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop 
*colorop,
struct 
drm_colorop_state *state)
 {
@@ -333,7 +357,8 @@ EXPORT_SYMBOL(drm_colorop_reset);
 static const char * const colorop_type_name[] = {
[DRM_COLOROP_1D_CURVE] = "1D Curve",
[DRM_COLOROP_1D_LUT] = "1D Curve Custom LUT",
-   [DRM_COLOROP_CTM_3X4] = "3x4 Matrix"
+   [DRM_COLOROP_CTM_3X4] = "3x4 Matrix",
+   [DRM_COLOROP_MULTIPLIER] = "Multiplier",
 };
 
 /**
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index 8adc7ece3bd1..f9f83644cc9f 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -64,6 +64,13 @@ struct drm_colorop_state {
 */
enum drm_colorop_curve_1d_type curve_1d_type;
 
+   /**
+* @multiplier:
+*
+* Multiplier to 'gain' the plane. Format is S31.32 sign-magnitude.
+*/
+   uint64_t multiplier;
+
/**
 * @size:
 *
@@ -186,6 +193,13 @@ struct drm_colorop {
 */
struct drm_property *curve_1d_type_property;
 
+   /**
+* @multiplier_property:
+*

[RFC PATCH v4 40/42] drm/amd/display: add 3x4 matrix colorop

2024-02-26 Thread Harry Wentland
From: Alex Hung 

This adds support for a 3x4 color transformation matrix.

With this change the following IGT tests pass:
kms_colorop --run plane-XR30-XR30-ctm_3x4_50_desat
kms_colorop --run plane-XR30-XR30-ctm_3x4_overdrive
kms_colorop --run plane-XR30-XR30-ctm_3x4_oversaturate
kms_colorop --run plane-XR30-XR30-ctm_3x4_bt709_enc
kms_colorop --run plane-XR30-XR30-ctm_3x4_bt709_dec

The color pipeline now consists of the following colorops:
1. 1D curve colorop
2. 3x4 CTM
3. 1D curve colorop
4. 1D LUT
5. 1D curve colorop
6. 1D LUT

Signed-off-by: Alex Hung 
Signed-off-by: Harry Wentland 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 50 +++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 15 ++
 2 files changed, 65 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index e7b51b29cc04..ef50640b362b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1212,6 +1212,45 @@ __set_dm_plane_colorop_degamma(struct drm_plane_state 
*plane_state,
return __set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state);
 }
 
+static int
+__set_dm_plane_colorop_3x4_matrix(struct drm_plane_state *plane_state,
+ struct dc_plane_state *dc_plane_state,
+ struct drm_colorop *colorop)
+{
+   struct drm_colorop *old_colorop;
+   struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+   struct drm_atomic_state *state = plane_state->state;
+   const struct drm_device *dev = colorop->dev;
+   const struct drm_property_blob *blob;
+   struct drm_color_ctm_3x4 *ctm = NULL;
+   int i = 0;
+
+   /* 3x4 matrix */
+   old_colorop = colorop;
+   for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+   if (new_colorop_state->colorop == old_colorop &&
+   new_colorop_state->colorop->type == DRM_COLOROP_CTM_3X4) {
+   colorop_state = new_colorop_state;
+   break;
+   }
+   }
+
+   if (colorop_state && !colorop_state->bypass && colorop->type == 
DRM_COLOROP_CTM_3X4) {
+   drm_dbg(dev, "3x4 matrix colorop with ID: %d\n", 
colorop->base.id);
+   blob = colorop_state->data;
+   if (blob->length == sizeof(struct drm_color_ctm_3x4)) {
+   ctm = blob ? (struct drm_color_ctm_3x4 *) blob->data : 
NULL;
+   __drm_ctm_3x4_to_dc_matrix(ctm, 
dc_plane_state->gamut_remap_matrix.matrix);
+   dc_plane_state->gamut_remap_matrix.enable_remap = true;
+   
dc_plane_state->input_csc_color_matrix.enable_adjustment = false;
+   } else
+   drm_warn(dev, "blob->length (%ld) isn't equal to 
drm_color_ctm_3x4 (%ld)\n",
+blob->length, sizeof(struct 
drm_color_ctm_3x4));
+   }
+
+   return 0;
+}
+
 static int
 __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
  struct dc_plane_state *dc_plane_state,
@@ -1411,6 +1450,17 @@ amdgpu_dm_plane_set_colorop_properties(struct 
drm_plane_state *plane_state,
if (ret)
return ret;
 
+   /* 3x4 matrix */
+   colorop = colorop->next;
+   if (!colorop) {
+   drm_dbg(dev, "no 3x4 matrix colorop found\n");
+   return -EINVAL;
+   }
+
+   ret = __set_dm_plane_colorop_3x4_matrix(plane_state, dc_plane_state, 
colorop);
+   if (ret)
+   return ret;
+
/* 1D Curve & LUT - SHAPER TF & LUT */
colorop = colorop->next;
if (!colorop) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index 08480bf61dc5..ba42f1f6b620 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -69,6 +69,21 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane 
*plane, struct drm_pr
 
prev_op = op;
 
+   /* 3x4 matrix */
+   op = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+   if (!op) {
+   DRM_ERROR("KMS: Failed to allocate colorop\n");
+   return -ENOMEM;
+   }
+
+   ret = drm_colorop_ctm_3x4_init(dev, op, plane);
+   if (ret)
+   return ret;
+
+   drm_colorop_set_next_property(prev_op, op);
+
+   prev_op = op;
+
/* 1D curve - SHAPER TF */
op = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
if (!op) {
-- 
2.44.0



[RFC PATCH v4 33/42] drm/amd/display: Add support for sRGB EOTF in BLND block

2024-02-26 Thread Harry Wentland
From: Alex Hung 

Expose a 3rd 1D curve colorop, with support for
DRM_COLOROP_1D_CURVE_SRGB_EOTF and program the BLND block
to perform the sRGB transform when the colorop is not in
bypass

With this change the following IGT test passes:
kms_colorop --run plane-XR30-XR30-srgb_eotf-srgb_inv_eotf-srgb_eotf

The color pipeline now consists of the following colorops:
1. 1D curve colorop w/ sRGB EOTF support
2. 1D curve colorop w/ sRGB Inverse EOTF support
3. 1D curve colorop w/ sRGB EOTF support

Signed-off-by: Alex Hung 
Signed-off-by: Harry Wentland 
Co-developed-by: Harry Wentland 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 77 +++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 18 +
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.h |  1 +
 3 files changed, 96 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 8788cfd26abd..3e3ae2b58b06 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1267,6 +1267,72 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state 
*plane_state,
return __set_colorop_in_shaper_1d_curve(dc_plane_state, colorop_state);
 }
 
+
+static int
+__set_colorop_1d_curve_blend_tf_lut(struct dc_plane_state *dc_plane_state,
+ struct drm_colorop_state *colorop_state)
+{
+
+   struct dc_transfer_func *tf = dc_plane_state->blend_tf;
+   struct drm_colorop *colorop = colorop_state->colorop;
+   struct drm_device *drm = colorop->dev;
+   const struct drm_color_lut *blend_lut;
+   uint32_t blend_size;
+
+   if (colorop->type != DRM_COLOROP_1D_CURVE &&
+   colorop_state->curve_1d_type != DRM_COLOROP_1D_CURVE_SRGB_EOTF)
+   return -EINVAL;
+
+   if (colorop_state->bypass) {
+   tf->type = TF_TYPE_BYPASS;
+   tf->tf = TRANSFER_FUNCTION_LINEAR;
+   return 0;
+   }
+
+   drm_dbg(drm, "Blend colorop with ID: %d\n", colorop->base.id);
+
+   if (colorop->type == DRM_COLOROP_1D_CURVE) {
+   tf->type = TF_TYPE_DISTRIBUTED_POINTS;
+   tf->tf = 
amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
+   tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
+   return __set_input_tf(NULL, tf, blend_lut, blend_size);
+   }
+
+   return -EINVAL;
+}
+
+static int
+__set_dm_plane_colorop_blend(struct drm_plane_state *plane_state,
+struct dc_plane_state *dc_plane_state,
+struct drm_colorop *colorop)
+{
+   struct drm_colorop *old_colorop;
+   struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+   struct drm_atomic_state *state = plane_state->state;
+   int i = 0;
+
+   old_colorop = colorop;
+
+   /* 3nd op: 1d curve - blend */
+   for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+   if (new_colorop_state->colorop == old_colorop &&
+   new_colorop_state->curve_1d_type == 
DRM_COLOROP_1D_CURVE_SRGB_EOTF) {
+   colorop_state = new_colorop_state;
+   break;
+   }
+
+   if (new_colorop_state->colorop == old_colorop) {
+   colorop_state = new_colorop_state;
+   break;
+   }
+   }
+
+   if (!colorop_state)
+   return -EINVAL;
+
+   return __set_colorop_1d_curve_blend_tf_lut(dc_plane_state, 
colorop_state);
+}
+
 static int
 amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
 struct dc_plane_state *dc_plane_state)
@@ -1345,6 +1411,17 @@ amdgpu_dm_plane_set_colorop_properties(struct 
drm_plane_state *plane_state,
if (ret)
return ret;
 
+   /* 1D Curve - BLND TF */
+   colorop = colorop->next;
+   if (!colorop) {
+   drm_dbg(dev, "no Blend TF colorop found\n");
+   return -EINVAL;
+   }
+
+   ret = __set_dm_plane_colorop_blend(plane_state, dc_plane_state, 
colorop);
+   if (ret)
+   return ret;
+
return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index 0d1626abf577..449a2ad6a184 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -37,6 +37,9 @@ const u64 amdgpu_dm_supported_degam_tfs =
  const u64 amdgpu_dm_supported_shaper_tfs =
BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF);
 
+const u64 amdgpu_dm_supported_blnd_tfs =
+   BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF);
+
 int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct 
drm_prop_enum_list *list)
 {
struct drm_colorop *op, *prev_op;
@@ -72,5 

[RFC PATCH v4 42/42] drm/amd/display: add multiplier colorop

2024-02-26 Thread Harry Wentland
From: Alex Hung 

This adds support for a multiplier. This multiplier is
programmed via the HDR Multiplier in DCN.

With this change the following IGT tests pass:
kms_colorop --run plane-XR30-XR30-multiply_125
kms_colorop --run plane-XR30-XR30-multiply_inv_125

The color pipeline now consists of the following colorops:
1. 1D curve colorop
2. 3x4 CTM
3. Multiplier
4. 1D curve colorop
5. 1D LUT
6. 1D curve colorop
7. 1D LUT

Signed-off-by: Alex Hung 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 40 +++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 15 +++
 2 files changed, 55 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index ef50640b362b..b05e4fea8a08 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1251,6 +1251,35 @@ __set_dm_plane_colorop_3x4_matrix(struct drm_plane_state 
*plane_state,
return 0;
 }
 
+static int
+__set_dm_plane_colorop_multiplier(struct drm_plane_state *plane_state,
+ struct dc_plane_state *dc_plane_state,
+ struct drm_colorop *colorop)
+{
+   struct drm_colorop *old_colorop;
+   struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+   struct drm_atomic_state *state = plane_state->state;
+   const struct drm_device *dev = colorop->dev;
+   int i = 0;
+
+   /* Multiplier */
+   old_colorop = colorop;
+   for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+   if (new_colorop_state->colorop == old_colorop &&
+   new_colorop_state->colorop->type == DRM_COLOROP_MULTIPLIER) 
{
+   colorop_state = new_colorop_state;
+   break;
+   }
+   }
+
+   if (colorop_state && !colorop_state->bypass && colorop->type == 
DRM_COLOROP_MULTIPLIER) {
+   drm_dbg(dev, "Multiplier colorop with ID: %d\n", 
colorop->base.id);
+   dc_plane_state->hdr_mult = 
amdgpu_dm_fixpt_from_s3132(colorop_state->multiplier);
+   }
+
+   return 0;
+}
+
 static int
 __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
  struct dc_plane_state *dc_plane_state,
@@ -1461,6 +1490,17 @@ amdgpu_dm_plane_set_colorop_properties(struct 
drm_plane_state *plane_state,
if (ret)
return ret;
 
+   /* Multiplier */
+   colorop = colorop->next;
+   if (!colorop) {
+   drm_dbg(dev, "no multiplier colorop found\n");
+   return -EINVAL;
+   }
+
+   ret = __set_dm_plane_colorop_multiplier(plane_state, dc_plane_state, 
colorop);
+   if (ret)
+   return ret;
+
/* 1D Curve & LUT - SHAPER TF & LUT */
colorop = colorop->next;
if (!colorop) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index ba42f1f6b620..b739d6cb3e6b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -84,6 +84,21 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane 
*plane, struct drm_pr
 
prev_op = op;
 
+   /* Multiplier */
+   op = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+   if (!op) {
+   DRM_ERROR("KMS: Failed to allocate colorop\n");
+   return -ENOMEM;
+   }
+
+   ret = drm_colorop_mult_init(dev, op, plane);
+   if (ret)
+   return ret;
+
+   drm_colorop_set_next_property(prev_op, op);
+
+   prev_op = op;
+
/* 1D curve - SHAPER TF */
op = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
if (!op) {
-- 
2.44.0



[RFC PATCH v4 08/42] drm/doc/rfc: Describe why prescriptive color pipeline is needed

2024-02-26 Thread Harry Wentland
v4:
 - Drop IOCTL docs since we dropped the IOCTLs (Pekka)
 - Clarify reading and setting of COLOR_PIPELINE prop (Pekka)
 - Add blurb about not requiring to reject a pipeline due to
   incompatible ops, as long as op can be bypassed (Pekka)
 - Dropped informational strings (such as input CSC) as they're
   not actually intended to be advertised (Pekka)

v3:
 - Describe DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE (Sebastian)
 - Ask for clear documentation of colorop behavior (Sebastian)

v2:
 - Update colorop visualizations to match reality (Sebastian, Alex Hung)
 - Updated wording (Pekka)
 - Change BYPASS wording to make it non-mandatory (Sebastian)
 - Drop cover-letter-like paragraph from COLOR_PIPELINE Plane Property
   section (Pekka)
 - Use PQ EOTF instead of its inverse in Pipeline Programming example (Melissa)
 - Add "Driver Implementer's Guide" section (Pekka)
 - Add "Driver Forward/Backward Compatibility" section (Sebastian, Pekka)

Signed-off-by: Harry Wentland 
---
 Documentation/gpu/rfc/color_pipeline.rst | 360 +++
 1 file changed, 360 insertions(+)
 create mode 100644 Documentation/gpu/rfc/color_pipeline.rst

diff --git a/Documentation/gpu/rfc/color_pipeline.rst 
b/Documentation/gpu/rfc/color_pipeline.rst
new file mode 100644
index ..6c653e17054a
--- /dev/null
+++ b/Documentation/gpu/rfc/color_pipeline.rst
@@ -0,0 +1,360 @@
+
+Linux Color Pipeline API
+
+
+What problem are we solving?
+
+
+We would like to support pre-, and post-blending complex color
+transformations in display controller hardware in order to allow for
+HW-supported HDR use-cases, as well as to provide support to
+color-managed applications, such as video or image editors.
+
+It is possible to support an HDR output on HW supporting the Colorspace
+and HDR Metadata drm_connector properties, but that requires the
+compositor or application to render and compose the content into one
+final buffer intended for display. Doing so is costly.
+
+Most modern display HW offers various 1D LUTs, 3D LUTs, matrices, and other
+operations to support color transformations. These operations are often
+implemented in fixed-function HW and therefore much more power efficient than
+performing similar operations via shaders or CPU.
+
+We would like to make use of this HW functionality to support complex color
+transformations with no, or minimal CPU or shader load.
+
+
+How are other OSes solving this problem?
+
+
+The most widely supported use-cases regard HDR content, whether video or
+gaming.
+
+Most OSes will specify the source content format (color gamut, encoding 
transfer
+function, and other metadata, such as max and average light levels) to a 
driver.
+Drivers will then program their fixed-function HW accordingly to map from a
+source content buffer's space to a display's space.
+
+When fixed-function HW is not available the compositor will assemble a shader 
to
+ask the GPU to perform the transformation from the source content format to the
+display's format.
+
+A compositor's mapping function and a driver's mapping function are usually
+entirely separate concepts. On OSes where a HW vendor has no insight into
+closed-source compositor code such a vendor will tune their color management
+code to visually match the compositor's. On other OSes, where both mapping
+functions are open to an implementer they will ensure both mappings match.
+
+This results in mapping algorithm lock-in, meaning that no-one alone can
+experiment with or introduce new mapping algorithms and achieve
+consistent results regardless of which implementation path is taken.
+
+Why is Linux different?
+===
+
+Unlike other OSes, where there is one compositor for one or more drivers, on
+Linux we have a many-to-many relationship. Many compositors; many drivers.
+In addition each compositor vendor or community has their own view of how
+color management should be done. This is what makes Linux so beautiful.
+
+This means that a HW vendor can now no longer tune their driver to one
+compositor, as tuning it to one could make it look fairly different from
+another compositor's color mapping.
+
+We need a better solution.
+
+
+Descriptive API
+===
+
+An API that describes the source and destination colorspaces is a descriptive
+API. It describes the input and output color spaces but does not describe
+how precisely they should be mapped. Such a mapping includes many minute
+design decision that can greatly affect the look of the final result.
+
+It is not feasible to describe such mapping with enough detail to ensure the
+same result from each implementation. In fact, these mappings are a very active
+research area.
+
+
+Prescriptive API
+
+
+A prescriptive API describes not the source and destination colorspaces. It
+instead prescribes a recipe for how to manipulate pixel values to arrive 

[RFC PATCH v4 20/42] drm/colorop: Add 3x4 CTM type

2024-02-26 Thread Harry Wentland
This type is used to support a 3x4 matrix in colorops. A 3x4
matrix uses the last column as a "bias" column. Some HW exposes
support for 3x4. The calculation looks like:

 out   matrixin
 |R|   |0  1  2  3 |   | R |
 |G| = |4  5  6  7 | x | G |
 |B|   |8  9  10 11|   | B |
   |1.0|

This is also the first colorop where we need a blob property to
program the property. For that we'll introduce a new DATA
property that can be used by all colorop TYPEs requiring a
blob. The way a DATA blob is read depends on the TYPE of
the colorop.

We only create the DATA property for property types that
need it.

v4:
 - Create helper function for creating 3x4 CTM colorop
 - Fix CTM indexes in comment (Pekka)

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/drm_atomic.c  | 14 ++-
 drivers/gpu/drm/drm_atomic_uapi.c | 29 ++
 drivers/gpu/drm/drm_colorop.c | 40 +++
 include/drm/drm_colorop.h | 19 +++
 include/uapi/drm/drm_mode.h   |  9 ++-
 5 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index d82858dabf06..6e736ffa6d7c 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -793,7 +793,19 @@ static void drm_atomic_colorop_print_state(struct 
drm_printer *p,
drm_printf(p, "colorop[%u]:\n", colorop->base.id);
drm_printf(p, "\ttype=%s\n", drm_get_colorop_type_name(colorop->type));
drm_printf(p, "\tbypass=%u\n", state->bypass);
-   drm_printf(p, "\tcurve_1d_type=%s\n", 
drm_get_colorop_curve_1d_type_name(state->curve_1d_type));
+
+   switch (colorop->type) {
+   case DRM_COLOROP_1D_CURVE:
+   drm_printf(p, "\tcurve_1d_type=%s\n",
+  
drm_get_colorop_curve_1d_type_name(state->curve_1d_type));
+   break;
+   case DRM_COLOROP_CTM_3X4:
+   drm_printf(p, "\tdata blob id=%d\n", state->data ? 
state->data->base.id : 0);
+   break;
+   default:
+   break;
+   }
+
drm_printf(p, "\tnext=%d\n", colorop->next ? colorop->next->base.id : 
0);
 }
 
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index ff258b34544e..23b248987a7c 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -691,6 +691,30 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
return 0;
 }
 
+static int drm_atomic_color_set_data_property(struct drm_colorop *colorop,
+   struct drm_colorop_state *state,
+   struct drm_property *property, uint64_t val)
+{
+   ssize_t elem_size = -1;
+   ssize_t size = -1;
+   bool replaced = false;
+
+   switch (colorop->type) {
+   case DRM_COLOROP_CTM_3X4:
+   size = sizeof(struct drm_color_ctm_3x4);
+   break;
+   default:
+   /* should never get here */
+   return -EINVAL;
+   }
+
+   return drm_property_replace_blob_from_id(colorop->dev,
+   >data,
+   val,
+   size,
+   elem_size,
+   );
+}
 
 static int drm_atomic_colorop_set_property(struct drm_colorop *colorop,
struct drm_colorop_state *state, struct drm_file *file_priv,
@@ -700,6 +724,9 @@ static int drm_atomic_colorop_set_property(struct 
drm_colorop *colorop,
state->bypass = val;
} else if (property == colorop->curve_1d_type_property) {
state->curve_1d_type = val;
+   } else if (property == colorop->data_property) {
+   return drm_atomic_color_set_data_property(colorop,
+   state, property, val);
} else {
drm_dbg_atomic(colorop->dev,
   "[COLOROP:%d:%d] unknown property 
[PROP:%d:%s]]\n",
@@ -722,6 +749,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
*val = state->bypass;
} else if (property == colorop->curve_1d_type_property) {
*val = state->curve_1d_type;
+   } else if (property == colorop->data_property) {
+   *val = (state->data) ? state->data->base.id : 0;
} else {
return -EINVAL;
}
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 71c2286333a1..7baa1eba 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -34,6 +34,7 @@
 
 static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
{ DRM_COLOROP_1D_CURVE, "1D Curve" },
+   { DRM_COLOROP_CTM_3X4, "3x4 Matrix"}
 };
 
 static const char * const colorop_curve_1d_type_names[] = {
@@ -93,6 +94,7 @@ int drm_colorop_init(struct drm_device *dev, struct 
drm_colorop 

[RFC PATCH v4 39/42] drm/amd/display: add shaper and blend colorops for 1D Curve Custom LUT

2024-02-26 Thread Harry Wentland
From: Alex Hung 

This patch adds colorops for custom 1D LUTs in the SHAPER and
BLND HW blocks.

With this change the following IGT tests pass:
kms_colorop --run plane-XR30-XR30-srgb_inv_eotf_lut
kms_colorop --run plane-XR30-XR30-srgb_inv_eotf_lut-srgb_eotf_lut

The color pipeline now consists of the following colorops:
1. 1D curve colorop
2. 1D curve colorop
3. 1D LUT
4. 1D curve colorop
5. 1D LUT

The 1D curve colorops support sRGB, BT2020, and PQ scaled to 125.0.

Signed-off-by: Alex Hung 
Signed-off-by: Harry Wentland 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 170 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c |  30 
 2 files changed, 119 insertions(+), 81 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index d5d356cf9fc6..e7b51b29cc04 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1212,40 +1212,6 @@ __set_dm_plane_colorop_degamma(struct drm_plane_state 
*plane_state,
return __set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state);
 }
 
-static int
-__set_colorop_in_shaper_1d_curve(struct dc_plane_state *dc_plane_state,
-  struct drm_colorop_state *colorop_state)
-{
-   struct dc_transfer_func *tf = dc_plane_state->in_shaper_func;
-   struct drm_colorop *colorop = colorop_state->colorop;
-   struct drm_device *drm = colorop->dev;
-   const struct drm_color_lut *shaper_lut;
-   uint32_t shaper_size;
-
-   if (colorop->type != DRM_COLOROP_1D_CURVE)
-   return -EINVAL;
-
-   if (!(BIT(colorop_state->curve_1d_type) & 
amdgpu_dm_supported_shaper_tfs))
-   return -EINVAL;
-
-   if (colorop_state->bypass) {
-   tf->type = TF_TYPE_BYPASS;
-   tf->tf = TRANSFER_FUNCTION_LINEAR;
-   return 0;
-   }
-
-   drm_dbg(drm, "Shaper colorop with ID: %d\n", colorop->base.id);
-
-   if (colorop->type == DRM_COLOROP_1D_CURVE) {
-   tf->type = TF_TYPE_DISTRIBUTED_POINTS;
-   tf->tf = 
amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
-   tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
-   return __set_output_tf(tf, shaper_lut, shaper_size, false);
-   }
-
-   return -EINVAL;
-}
-
 static int
 __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
  struct dc_plane_state *dc_plane_state,
@@ -1254,64 +1220,61 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state 
*plane_state,
struct drm_colorop *old_colorop;
struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
struct drm_atomic_state *state = plane_state->state;
+   enum dc_transfer_func_predefined default_tf = TRANSFER_FUNCTION_LINEAR;
+   struct dc_transfer_func *tf = dc_plane_state->in_shaper_func;
+   const struct drm_color_lut *shaper_lut;
+   struct drm_device *dev = colorop->dev;
+   uint32_t shaper_size;
int i = 0;
 
+   /* 1D Curve - SHAPER TF */
old_colorop = colorop;
-
-   /* 2nd op: 1d curve - shaper */
for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
if (new_colorop_state->colorop == old_colorop &&
(BIT(new_colorop_state->curve_1d_type) & 
amdgpu_dm_supported_shaper_tfs)) {
colorop_state = new_colorop_state;
break;
}
+   }
 
-   if (new_colorop_state->colorop == old_colorop) {
+   if (colorop_state && !colorop_state->bypass && colorop->type == 
DRM_COLOROP_1D_CURVE) {
+   drm_dbg(dev, "Shaper TF colorop with ID: %d\n", 
colorop->base.id);
+   tf->type = TF_TYPE_DISTRIBUTED_POINTS;
+   tf->tf = default_tf = 
amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
+   tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
+   __set_output_tf(tf, shaper_lut, shaper_size, false);
+   }
+
+   /* 1D LUT - SHAPER LUT */
+   colorop = old_colorop->next;
+   if (!colorop) {
+   drm_dbg(dev, "no Shaper LUT colorop found\n");
+   return -EINVAL;
+   }
+
+   old_colorop = colorop;
+   for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+   if (new_colorop_state->colorop == old_colorop &&
+   new_colorop_state->colorop->type == DRM_COLOROP_1D_LUT) {
colorop_state = new_colorop_state;
break;
}
}
 
-   if (!colorop_state)
-   return -EINVAL;
-
-   return __set_colorop_in_shaper_1d_curve(dc_plane_state, colorop_state);
-}
-
-
-static int
-__set_colorop_1d_curve_blend_tf_lut(struct dc_plane_state *dc_plane_state,
- 

[RFC PATCH v4 36/42] drm/colorop: add BT2020/BT709 OETF and Inverse OETF

2024-02-26 Thread Harry Wentland
The BT.709 and BT.2020 OETFs are the same, the only difference
being that the BT.2020 variant is defined with more precision
for 10 and 12-bit per color encodings.

Both are used as encoding functions for video content, and are
therefore defined as OETF (opto-electronic transfer function)
instead of as EOTF (electro-optical transfer function).

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/drm_colorop.c | 2 ++
 include/drm/drm_colorop.h | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 781947e42b02..b10cad5a7208 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -40,6 +40,8 @@ static const struct drm_prop_enum_list 
drm_colorop_type_enum_list[] = {
 static const char * const colorop_curve_1d_type_names[] = {
[DRM_COLOROP_1D_CURVE_SRGB_EOTF] = "sRGB EOTF",
[DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF] = "sRGB Inverse EOTF",
+   [DRM_COLOROP_1D_CURVE_BT2020_INV_OETF] = "BT.2020 Inverse OETF",
+   [DRM_COLOROP_1D_CURVE_BT2020_OETF] = "BT.2020 OETF",
[DRM_COLOROP_1D_CURVE_PQ_125_EOTF] = "PQ 125 EOTF",
[DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF] = "PQ 125 Inverse EOTF",
 };
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index e06d9ea28efd..28b3136dabad 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -33,6 +33,8 @@
 enum drm_colorop_curve_1d_type {
DRM_COLOROP_1D_CURVE_SRGB_EOTF,
DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF,
+   DRM_COLOROP_1D_CURVE_BT2020_INV_OETF,
+   DRM_COLOROP_1D_CURVE_BT2020_OETF,
DRM_COLOROP_1D_CURVE_PQ_125_EOTF,
DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF,
DRM_COLOROP_1D_CURVE_COUNT
-- 
2.44.0



[RFC PATCH v4 30/42] drm/amd/display: Skip color pipeline initialization for cursor plane

2024-02-26 Thread Harry Wentland
From: Alex Hung 

Signed-off-by: Alex Hung 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index c5c07b4cd6c9..d3f64f586243 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1659,6 +1659,9 @@ dm_plane_init_colorops(struct drm_plane *plane)
struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
int len = 0;
 
+   if (plane->type == DRM_PLANE_TYPE_CURSOR)
+   return 0;
+
/* Create COLOR_PIPELINE property and attach */
drm_plane_create_color_pipeline_property(plane, pipelines, len);
 
-- 
2.44.0



[RFC PATCH v4 38/42] drm/colorop: Add 1D Curve Custom LUT type

2024-02-26 Thread Harry Wentland
From: Alex Hung 

We've previously introduced DRM_COLOROP_1D_CURVE for
pre-defined 1D curves. But we also have HW that supports
custom curves and userspace needs the ability to pass
custom curves, aka LUTs.

This patch introduces a new colorop type, called
DRM_COLOROP_1D_LUT that provides a SIZE property which
is used by a driver to advertise the supported SIZE
of the LUT, as well as a DATA property which userspace
uses to set the LUT.

DATA and size function in the same way as current drm_crtc
GAMMA and DEGAMMA LUTs.

Signed-off-by: Alex Hung 
Signed-off-by: Harry Wentland 
Co-developed-by: Harry Wentland 
---
 drivers/gpu/drm/drm_atomic.c  |  4 
 drivers/gpu/drm/drm_atomic_uapi.c |  5 +
 drivers/gpu/drm/drm_colorop.c | 36 +--
 include/drm/drm_colorop.h | 16 ++
 include/uapi/drm/drm_mode.h   |  1 +
 5 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 6e736ffa6d7c..f7d51839ca03 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -799,6 +799,10 @@ static void drm_atomic_colorop_print_state(struct 
drm_printer *p,
drm_printf(p, "\tcurve_1d_type=%s\n",
   
drm_get_colorop_curve_1d_type_name(state->curve_1d_type));
break;
+   case DRM_COLOROP_1D_LUT:
+   drm_printf(p, "\tsize=%d\n", state->size);
+   drm_printf(p, "\tdata blob id=%d\n", state->data ? 
state->data->base.id : 0);
+   break;
case DRM_COLOROP_CTM_3X4:
drm_printf(p, "\tdata blob id=%d\n", state->data ? 
state->data->base.id : 0);
break;
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index c7c1c614b0d9..6bfe857720cd 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -700,6 +700,9 @@ static int drm_atomic_color_set_data_property(struct 
drm_colorop *colorop,
bool replaced = false;
 
switch (colorop->type) {
+   case DRM_COLOROP_1D_LUT:
+   size = state->size * sizeof(struct drm_color_lut);
+   break;
case DRM_COLOROP_CTM_3X4:
size = sizeof(struct drm_color_ctm_3x4);
break;
@@ -749,6 +752,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
*val = state->bypass;
} else if (property == colorop->curve_1d_type_property) {
*val = state->curve_1d_type;
+   } else if (property == colorop->size_property) {
+   *val = state->size;
} else if (property == colorop->data_property) {
*val = (state->data) ? state->data->base.id : 0;
} else {
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index b10cad5a7208..4452eaeeb242 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -34,6 +34,7 @@
 
 static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
{ DRM_COLOROP_1D_CURVE, "1D Curve" },
+   { DRM_COLOROP_1D_LUT, "1D Curve Custom LUT" },
{ DRM_COLOROP_CTM_3X4, "3x4 Matrix"}
 };
 
@@ -175,11 +176,41 @@ static int drm_colorop_create_data_prop(struct drm_device 
*dev, struct drm_color
 
colorop->data_property = prop;
drm_object_attach_property(>base,
-   colorop->data_property,
-   0);
+  colorop->data_property,
+  0);
 
return 0;
 }
+int drm_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop 
*colorop,
+ struct drm_plane *plane, uint32_t lut_size)
+{
+   struct drm_property *prop;
+   int ret;
+
+   ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_1D_LUT);
+   if (ret)
+   return ret;
+
+   /* initialize 1D LUT only attribute */
+   /* LUT size */
+   prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, "SIZE", 
lut_size, lut_size);
+   if (!prop)
+   return -ENOMEM;
+
+   colorop->size_property = prop;
+   drm_object_attach_property(>base, colorop->size_property, 0);
+
+   /* data */
+   ret = drm_colorop_create_data_prop(dev, colorop);
+   if (ret)
+   return ret;
+
+   drm_colorop_reset(colorop);
+   colorop->state->size = lut_size;
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_colorop_curve_1d_lut_init);
 
 int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop 
*colorop,
 struct drm_plane *plane)
@@ -301,6 +332,7 @@ EXPORT_SYMBOL(drm_colorop_reset);
 
 static const char * const colorop_type_name[] = {
[DRM_COLOROP_1D_CURVE] = "1D Curve",
+   [DRM_COLOROP_1D_LUT] = "1D Curve Custom LUT",
[DRM_COLOROP_CTM_3X4] = "3x4 Matrix"
 };
 
diff --git 

[RFC PATCH v4 34/42] drm/colorop: Add PQ 125 EOTF and its inverse

2024-02-26 Thread Harry Wentland
The PQ function defines a mapping of code values to nits (cd/m^2).
The max code value maps to 10,000 nits.

Windows DWM's canonical composition color space (CCCS)  defaults
to composing SDR contents to 80 nits and uses a float value of
1.0 to represent this. For this reason AMD HW hard-codes a PQ
function that is scaled by 125, yielding 80 nit PQ values for
1.0 and 10,000 nits at 125.0.

This patch introduces this scaled PQ EOTF and its inverse as
1D curve types.

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/drm_colorop.c | 2 ++
 include/drm/drm_colorop.h | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 7baa1eba..781947e42b02 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -40,6 +40,8 @@ static const struct drm_prop_enum_list 
drm_colorop_type_enum_list[] = {
 static const char * const colorop_curve_1d_type_names[] = {
[DRM_COLOROP_1D_CURVE_SRGB_EOTF] = "sRGB EOTF",
[DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF] = "sRGB Inverse EOTF",
+   [DRM_COLOROP_1D_CURVE_PQ_125_EOTF] = "PQ 125 EOTF",
+   [DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF] = "PQ 125 Inverse EOTF",
 };
 
 
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index 8710e550790c..e06d9ea28efd 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -33,6 +33,8 @@
 enum drm_colorop_curve_1d_type {
DRM_COLOROP_1D_CURVE_SRGB_EOTF,
DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF,
+   DRM_COLOROP_1D_CURVE_PQ_125_EOTF,
+   DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF,
DRM_COLOROP_1D_CURVE_COUNT
 };
 
-- 
2.44.0



[RFC PATCH v4 02/42] drm: Add helper for conversion from signed-magnitude

2024-02-26 Thread Harry Wentland
CTM values are defined as signed-magnitude values. Add
a helper that converts from CTM signed-magnitude fixed
point value to the twos-complement value used by
drm_fixed.

Signed-off-by: Harry Wentland 
---
 include/drm/drm_fixed.h | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/include/drm/drm_fixed.h b/include/drm/drm_fixed.h
index 0c9f917a4d4b..cb842ba80ddd 100644
--- a/include/drm/drm_fixed.h
+++ b/include/drm/drm_fixed.h
@@ -78,6 +78,24 @@ static inline u32 dfixed_div(fixed20_12 A, fixed20_12 B)
 #define DRM_FIXED_EPSILON  1LL
 #define DRM_FIXED_ALMOST_ONE   (DRM_FIXED_ONE - DRM_FIXED_EPSILON)
 
+/**
+ * @drm_sm2fixp
+ *
+ * Convert a 1.31.32 signed-magnitude fixed point to 32.32
+ * 2s-complement fixed point
+ *
+ * @return s64 2s-complement fixed point
+ */
+static inline s64 drm_sm2fixp(__u64 a)
+{
+   if ((a & (1LL << 63))) {
+   return -(a & 0x7fffll);
+   } else {
+   return a;
+   }
+
+}
+
 static inline s64 drm_int2fixp(int a)
 {
return ((s64)a) << DRM_FIXED_POINT;
-- 
2.44.0



[RFC PATCH v4 29/42] drm/amd/display: Add bypass COLOR PIPELINE

2024-02-26 Thread Harry Wentland
Add the default Bypass pipeline and ensure it passes the
kms_colorop test plane-XR30-XR30-bypass.

Signed-off-by: Harry Wentland 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index 8a4c40b4c27e..c5c07b4cd6c9 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1651,6 +1651,20 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
 }
 #endif
 
+#define MAX_COLOR_PIPELINES 5
+
+static int
+dm_plane_init_colorops(struct drm_plane *plane)
+{
+   struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
+   int len = 0;
+
+   /* Create COLOR_PIPELINE property and attach */
+   drm_plane_create_color_pipeline_property(plane, pipelines, len);
+
+   return 0;
+}
+
 static const struct drm_plane_funcs dm_plane_funcs = {
.update_plane   = drm_atomic_helper_update_plane,
.disable_plane  = drm_atomic_helper_disable_plane,
@@ -1744,7 +1758,12 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager 
*dm,
 
 #ifdef AMD_PRIVATE_COLOR
dm_atomic_plane_attach_color_mgmt_properties(dm, plane);
+#else
+   res = dm_plane_init_colorops(plane);
+   if (res)
+   return res;
 #endif
+
/* Create (reset) the plane state */
if (plane->funcs->reset)
plane->funcs->reset(plane);
-- 
2.44.0



[RFC PATCH v4 37/42] drm/amd/display: Add support for BT.709 and BT.2020 TFs

2024-02-26 Thread Harry Wentland
This adds support for the BT.709/BT.2020 transfer functions
on all current 1D curve plane colorops, i.e., on DEGAM, SHAPER,
and BLND blocks.

With this change the following IGT subtests pass:
kms_colorop --run plane-XR30-XR30-bt2020_inv_oetf
kms_colorop --run plane-XR30-XR30-bt2020_oetf

Signed-off-by: Harry Wentland 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c   | 11 ---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 10 +++---
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 20b7eb47388c..d5d356cf9fc6 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -677,6 +677,9 @@ amdgpu_colorop_tf_to_dc_tf(enum drm_colorop_curve_1d_type 
tf)
case DRM_COLOROP_1D_CURVE_SRGB_EOTF:
case DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF:
return TRANSFER_FUNCTION_SRGB;
+   case DRM_COLOROP_1D_CURVE_BT2020_INV_OETF:
+   case DRM_COLOROP_1D_CURVE_BT2020_OETF:
+   return TRANSFER_FUNCTION_BT709;
case DRM_COLOROP_1D_CURVE_PQ_125_EOTF:
case DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF:
return TRANSFER_FUNCTION_PQ;
@@ -1287,8 +1290,10 @@ __set_colorop_1d_curve_blend_tf_lut(struct 
dc_plane_state *dc_plane_state,
const struct drm_color_lut *blend_lut;
uint32_t blend_size;
 
-   if (colorop->type != DRM_COLOROP_1D_CURVE &&
-   colorop_state->curve_1d_type != DRM_COLOROP_1D_CURVE_SRGB_EOTF)
+   if (colorop->type != DRM_COLOROP_1D_CURVE)
+   return -EINVAL;
+
+   if (!(BIT(colorop_state->curve_1d_type) & amdgpu_dm_supported_blnd_tfs))
return -EINVAL;
 
if (colorop_state->bypass) {
@@ -1324,7 +1329,7 @@ __set_dm_plane_colorop_blend(struct drm_plane_state 
*plane_state,
/* 3nd op: 1d curve - blend */
for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
if (new_colorop_state->colorop == old_colorop &&
-   new_colorop_state->curve_1d_type == 
DRM_COLOROP_1D_CURVE_SRGB_EOTF) {
+   (BIT(new_colorop_state->curve_1d_type) & 
amdgpu_dm_supported_blnd_tfs)) {
colorop_state = new_colorop_state;
break;
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index f99d8e09d89b..bc66bd4f9fdd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -33,14 +33,18 @@
 
 const u64 amdgpu_dm_supported_degam_tfs =
BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
-   BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF);
+   BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) |
+   BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF);
 
 const u64 amdgpu_dm_supported_shaper_tfs =
BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF) |
-   BIT(DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF);
+   BIT(DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF) |
+   BIT(DRM_COLOROP_1D_CURVE_BT2020_OETF);
 
 const u64 amdgpu_dm_supported_blnd_tfs =
-   BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF);
+   BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
+   BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) |
+   BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF);
 
 int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct 
drm_prop_enum_list *list)
 {
-- 
2.44.0



[RFC PATCH v4 11/42] drm/colorop: Add 1D Curve subtype

2024-02-26 Thread Harry Wentland
v4:
 - Use drm_colorop_curve_1d_type_enum_list to get name (Pekka)
 - Create separate init function for 1D curve
 - Pass supported TFs into 1D curve init function

Signed-off-by: Harry Wentland 
Signed-off-by: Alex Hung 
Co-developed-by: Alex Hung 
---
 drivers/gpu/drm/drm_atomic_uapi.c | 18 +---
 drivers/gpu/drm/drm_colorop.c | 71 +++
 include/drm/drm_colorop.h | 24 +++
 3 files changed, 108 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index e3067c095c72..fdd540cfe24f 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -648,11 +648,17 @@ static int drm_atomic_colorop_set_property(struct 
drm_colorop *colorop,
struct drm_colorop_state *state, struct drm_file *file_priv,
struct drm_property *property, uint64_t val)
 {
-   drm_dbg_atomic(colorop->dev,
-   "[COLOROP:%d] unknown property [PROP:%d:%s]]\n",
-   colorop->base.id,
-   property->base.id, property->name);
-   return -EINVAL;
+   if (property == colorop->curve_1d_type_property) {
+   state->curve_1d_type = val;
+   } else {
+   drm_dbg_atomic(colorop->dev,
+  "[COLOROP:%d:%d] unknown property 
[PROP:%d:%s]]\n",
+  colorop->base.id, colorop->type,
+  property->base.id, property->name);
+   return -EINVAL;
+   }
+
+   return 0;
 }
 
 static int
@@ -662,6 +668,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
 {
if (property == colorop->type_property) {
*val = colorop->type;
+   } else if (property == colorop->curve_1d_type_property) {
+   *val = state->curve_1d_type;
} else {
return -EINVAL;
}
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 3a07a8fe2842..f4740b6115d1 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -36,6 +36,12 @@ static const struct drm_prop_enum_list 
drm_colorop_type_enum_list[] = {
{ DRM_COLOROP_1D_CURVE, "1D Curve" },
 };
 
+static const char * const colorop_curve_1d_type_names[] = {
+   [DRM_COLOROP_1D_CURVE_SRGB_EOTF] = "sRGB EOTF",
+   [DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF] = "sRGB Inverse EOTF",
+};
+
+
 /* Init Helpers */
 
 int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
@@ -78,6 +84,56 @@ int drm_colorop_init(struct drm_device *dev, struct 
drm_colorop *colorop,
 }
 EXPORT_SYMBOL(drm_colorop_init);
 
+int drm_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop 
*colorop,
+ struct drm_plane *plane, u64 supported_tfs)
+{
+   struct drm_prop_enum_list enum_list[DRM_COLOROP_1D_CURVE_COUNT];
+   int i, len;
+
+   struct drm_property *prop;
+   int ret;
+
+   if (!supported_tfs) {
+   drm_err(dev,
+   "No supported TFs for new 1D curve colorop on 
[PLANE:%d:%s]\n",
+   plane->base.id, plane->name);
+   return -EINVAL;
+   }
+
+   if ((supported_tfs & -BIT(DRM_COLOROP_1D_CURVE_COUNT)) != 0) {
+   drm_err(dev, "Unknown TF provided on [PLANE:%d:%s]\n",
+   plane->base.id, plane->name);
+   return -EINVAL;
+   }
+
+   ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_1D_CURVE);
+   if (ret)
+   return ret;
+
+   len = 0;
+   for (i = 0; i < DRM_COLOROP_1D_CURVE_COUNT; i++) {
+   if ((supported_tfs & BIT(i)) == 0)
+   continue;
+
+   enum_list[len].type = i;
+   enum_list[len].name = colorop_curve_1d_type_names[i];
+   len++;
+   }
+
+   /* initialize 1D curve only attribute */
+   prop = drm_property_create_enum(dev, DRM_MODE_PROP_ATOMIC, 
"CURVE_1D_TYPE",
+   enum_list, len);
+   if (!prop)
+   return -ENOMEM;
+
+   colorop->curve_1d_type_property = prop;
+   drm_object_attach_property(>base, 
colorop->curve_1d_type_property, 0);
+   drm_colorop_reset(colorop);
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_colorop_curve_1d_init);
+
 static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop 
*colorop,
struct 
drm_colorop_state *state)
 {
@@ -192,3 +248,18 @@ const char *drm_get_colorop_type_name(enum 
drm_colorop_type type)
 
return colorop_type_name[type];
 }
+
+/**
+ * drm_get_colorop_curve_1d_type_name - return a string for 1D curve type
+ * @range: 1d curve type to compute name of
+ *
+ * In contrast to the other drm_get_*_name functions this one here returns a
+ * const pointer and hence is threadsafe.
+ */
+const char 

[RFC PATCH v4 16/42] drm/colorop: Add NEXT to colorop state print

2024-02-26 Thread Harry Wentland
v3:
 - Read NEXT ID from drm_colorop's next pointer

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/drm_atomic.c | 1 +
 include/drm/drm_colorop.h| 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 27a8805c5fa1..d82858dabf06 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -794,6 +794,7 @@ static void drm_atomic_colorop_print_state(struct 
drm_printer *p,
drm_printf(p, "\ttype=%s\n", drm_get_colorop_type_name(colorop->type));
drm_printf(p, "\tbypass=%u\n", state->bypass);
drm_printf(p, "\tcurve_1d_type=%s\n", 
drm_get_colorop_curve_1d_type_name(state->curve_1d_type));
+   drm_printf(p, "\tnext=%d\n", colorop->next ? colorop->next->base.id : 
0);
 }
 
 static void drm_atomic_plane_print_state(struct drm_printer *p,
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index fc9a28d138b8..e85ed5aa68d0 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -237,6 +237,8 @@ const char *drm_get_colorop_type_name(enum drm_colorop_type 
type);
 const char *drm_get_colorop_curve_1d_type_name(enum drm_colorop_curve_1d_type 
type);
 
 void drm_colorop_set_next_property(struct drm_colorop *colorop, struct 
drm_colorop *next);
+uint32_t drm_colorop_get_next_property(struct drm_colorop *colorop);
+struct drm_colorop *drm_colorop_get_next(struct drm_colorop *colorop);
 
 
 #endif /* __DRM_COLOROP_H__ */
-- 
2.44.0



[RFC PATCH v4 19/42] drm/colorop: Introduce DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE

2024-02-26 Thread Harry Wentland
With the introduction of the pre-blending color pipeline we
can no longer have color operations that don't have a clear
position in the color pipeline. We deprecate all existing
plane properties. For upstream drivers those are:
 - COLOR_ENCODING
 - COLOR_RANGE

Drivers are expected to ignore these properties when
programming the HW.

Setting of the COLOR_PIPELINE plane property or drm_colorop
properties is only allowed for userspace that sets this
client cap.

v4:
 - Don't block setting of COLOR_RANGE and COLOR_ENCODING
   when client cap is set

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/drm_atomic_uapi.c | 13 -
 drivers/gpu/drm/drm_ioctl.c   |  7 +++
 include/drm/drm_file.h|  7 +++
 include/uapi/drm/drm.h| 16 
 4 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index 86f77a9aa3a8..ff258b34544e 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -570,6 +570,12 @@ static int drm_atomic_plane_set_property(struct drm_plane 
*plane,
} else if (property == plane->color_range_property) {
state->color_range = val;
} else if (property == plane->color_pipeline_property) {
+   if (!file_priv->plane_color_pipeline) {
+   drm_dbg_atomic(dev,
+  "Setting COLOR_PIPELINE plane property 
not permitted unless DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set\n");
+   return -EINVAL;
+   }
+
/* find DRM colorop object */
struct drm_colorop *colorop = NULL;
colorop = drm_colorop_find(dev, file_priv, val);
@@ -1179,6 +1185,12 @@ int drm_atomic_set_property(struct drm_atomic_state 
*state,
break;
}
case DRM_MODE_OBJECT_COLOROP: {
+   if (!file_priv->plane_color_pipeline) {
+   drm_dbg_atomic(prop->dev,
+  "[OBJECT:%d] is a colorop but 
DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE not set\n",
+  obj->id);
+   ret = -EINVAL;
+   }
struct drm_colorop *colorop = obj_to_colorop(obj);
struct drm_colorop_state *colorop_state;
 
@@ -1191,7 +1203,6 @@ int drm_atomic_set_property(struct drm_atomic_state 
*state,
ret = drm_atomic_colorop_set_property(colorop,
colorop_state, file_priv,
prop, prop_value);
-
break;
}
default:
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index e368fc084c77..da59e37ae228 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -373,6 +373,13 @@ drm_setclientcap(struct drm_device *dev, void *data, 
struct drm_file *file_priv)
return -EINVAL;
file_priv->supports_virtualized_cursor_plane = req->value;
break;
+   case DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE:
+   if (!file_priv->atomic)
+   return -EINVAL;
+   if (req->value > 1)
+   return -EINVAL;
+   file_priv->plane_color_pipeline = req->value;
+   break;
default:
return -EINVAL;
}
diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
index ab230d3af138..63c1d29b8520 100644
--- a/include/drm/drm_file.h
+++ b/include/drm/drm_file.h
@@ -204,6 +204,13 @@ struct drm_file {
 */
bool writeback_connectors;
 
+   /**
+* @plane_color_pipeline:
+*
+* True if client understands plane color pipelines
+*/
+   bool plane_color_pipeline;
+
/**
 * @was_master:
 *
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index 16122819edfe..2d74c49274ee 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -875,6 +875,22 @@ struct drm_get_cap {
  */
 #define DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT6
 
+/**
+ * DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE
+ *
+ * If set to 1
+ * - the DRM core will allow setting of plane the COLOR_PIPELINE
+ *   property, as well as drm_colorop properties.
+ * - Drivers will ignore these properties
+ *   - COLOR_ENCODING
+ *   - COLOR_RANGE
+ *
+ * The client must enable _CLIENT_CAP_ATOMIC first.
+ *
+ * This capability is currently in development.
+ */
+#define DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE7
+
 /* DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
 struct drm_set_client_cap {
__u64 capability;
-- 
2.44.0



[RFC PATCH v4 23/42] drm/vkms: add 3x4 matrix in color pipeline

2024-02-26 Thread Harry Wentland
We add two 3x4 matrices into the VKMS color pipeline. The reason
we're adding matrices is so that we can test that application
of a matrix and its inverse yields an output equal to the input
image.

One complication with the matrix implementation has to do with
the fact that the matrix entries are in signed-magnitude fixed
point, whereas the drm_fixed.h implementation uses 2s-complement.
The latter one is the one that we want for easy addition and
subtraction, so we convert all entries to 2s-complement.

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/vkms/vkms_colorop.c  | 32 +++-
 drivers/gpu/drm/vkms/vkms_composer.c | 27 +++
 include/drm/drm_colorop.h|  2 ++
 3 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c 
b/drivers/gpu/drm/vkms/vkms_colorop.c
index d2db366da6d3..a0e54b2c1f7a 100644
--- a/drivers/gpu/drm/vkms/vkms_colorop.c
+++ b/drivers/gpu/drm/vkms/vkms_colorop.c
@@ -35,7 +35,37 @@ const int vkms_initialize_color_pipeline(struct drm_plane 
*plane, struct drm_pro
 
prev_op = op;
 
-   /* 2nd op: 1d curve */
+   /* 2nd op: 3x4 matrix */
+   op = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+   if (!op) {
+   DRM_ERROR("KMS: Failed to allocate colorop\n");
+   return -ENOMEM;
+   }
+
+   ret = drm_colorop_ctm_3x4_init(dev, op, plane);
+   if (ret)
+   return ret;
+
+   drm_colorop_set_next_property(prev_op, op);
+
+   prev_op = op;
+
+   /* 3rd op: 3x4 matrix */
+   op = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+   if (!op) {
+   DRM_ERROR("KMS: Failed to allocate colorop\n");
+   return -ENOMEM;
+   }
+
+   ret = drm_colorop_ctm_3x4_init(dev, op, plane);
+   if (ret)
+   return ret;
+
+   drm_colorop_set_next_property(prev_op, op);
+
+   prev_op = op;
+
+   /* 4th op: 1d curve */
op = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
if (!op) {
DRM_ERROR("KMS: Failed to allocate colorop\n");
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index d2101fa55aa3..8bbfce651526 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -164,6 +164,30 @@ static void apply_lut(const struct vkms_crtc_state 
*crtc_state, struct line_buff
}
 }
 
+static void apply_3x4_matrix(struct pixel_argb_s32 *pixel, const struct 
drm_color_ctm_3x4 *matrix)
+{
+   s64 rf, gf, bf;
+
+   rf = drm_fixp_mul(drm_sm2fixp(matrix->matrix[0]), 
drm_int2fixp(pixel->r)) +
+drm_fixp_mul(drm_sm2fixp(matrix->matrix[1]), 
drm_int2fixp(pixel->g)) +
+drm_fixp_mul(drm_sm2fixp(matrix->matrix[2]), 
drm_int2fixp(pixel->b)) +
+drm_sm2fixp(matrix->matrix[3]);
+
+   gf = drm_fixp_mul(drm_sm2fixp(matrix->matrix[4]), 
drm_int2fixp(pixel->r)) +
+drm_fixp_mul(drm_sm2fixp(matrix->matrix[5]), 
drm_int2fixp(pixel->g)) +
+drm_fixp_mul(drm_sm2fixp(matrix->matrix[6]), 
drm_int2fixp(pixel->b)) +
+drm_sm2fixp(matrix->matrix[7]);
+
+   bf = drm_fixp_mul(drm_sm2fixp(matrix->matrix[8]), 
drm_int2fixp(pixel->r)) +
+drm_fixp_mul(drm_sm2fixp(matrix->matrix[9]), 
drm_int2fixp(pixel->g)) +
+drm_fixp_mul(drm_sm2fixp(matrix->matrix[10]), 
drm_int2fixp(pixel->b)) +
+drm_sm2fixp(matrix->matrix[11]);
+
+   pixel->r = drm_fixp2int(rf);
+   pixel->g = drm_fixp2int(gf);
+   pixel->b = drm_fixp2int(bf);
+}
+
 static void apply_colorop(struct pixel_argb_s32 *pixel, struct drm_colorop 
*colorop)
 {
/* TODO is this right? */
@@ -185,6 +209,9 @@ static void apply_colorop(struct pixel_argb_s32 *pixel, 
struct drm_colorop *colo
DRM_DEBUG_DRIVER("unkown colorop 1D curve type 
%d\n", colorop_state->curve_1d_type);
break;
}
+   } else if (colorop->type == DRM_COLOROP_CTM_3X4) {
+   if (colorop_state->data)
+   apply_3x4_matrix(pixel, (struct drm_color_ctm_3x4 *) 
colorop_state->data->data);
}
 
 }
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index 4aee29e161d6..8710e550790c 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -224,6 +224,8 @@ int drm_colorop_init(struct drm_device *dev, struct 
drm_colorop *colorop,
 
 int drm_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop 
*colorop,
  struct drm_plane *plane, u64 supported_tfs);
+int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop 
*colorop,
+struct drm_plane *plane);
 
 struct drm_colorop_state *
 drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop);
-- 
2.44.0



[RFC PATCH v4 25/42] drm/vkms: Add tests for CTM handling

2024-02-26 Thread Harry Wentland
A whole slew of tests for CTM handling that greatly helped in
debugging the CTM code. The extent of tests might seem a bit
silly but they're fast and might someday help save someone
else's day when debugging this.

v4:
 - Comment on origin of bt709_enc matrix (Pekka)
 - Use full opaque alpha (Pekka)
 - Add additional check for Y < 0x (Pekka)
 - Remove unused code (Pekka)
 - Rename red, green, blue to Y, U, V where applicable

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/vkms/tests/vkms_color_tests.c | 251 ++
 drivers/gpu/drm/vkms/vkms_composer.c  |   2 +-
 2 files changed, 252 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vkms/tests/vkms_color_tests.c 
b/drivers/gpu/drm/vkms/tests/vkms_color_tests.c
index e6ac01dee830..83d07f7bae37 100644
--- a/drivers/gpu/drm/vkms/tests/vkms_color_tests.c
+++ b/drivers/gpu/drm/vkms/tests/vkms_color_tests.c
@@ -3,6 +3,7 @@
 #include 
 
 #include 
+#include 
 
 #define TEST_LUT_SIZE 16
 
@@ -181,11 +182,261 @@ static void vkms_color_srgb_inv_srgb(struct kunit *test)
}
 }
 
+#define FIXPT_HALF(DRM_FIXED_ONE >> 1)
+#define FIXPT_QUARTER (DRM_FIXED_ONE >> 2)
+
+const struct drm_color_ctm_3x4 test_matrix_3x4_50_desat = { {
+   FIXPT_HALF, FIXPT_QUARTER, FIXPT_QUARTER, 0,
+   FIXPT_QUARTER, FIXPT_HALF, FIXPT_QUARTER, 0,
+   FIXPT_QUARTER, FIXPT_QUARTER, FIXPT_HALF, 0
+} };
+
+static void vkms_color_ctm_3x4_50_desat(struct kunit *test)
+{
+   struct pixel_argb_s32 ref, out;
+
+   /* full white */
+   ref.a = 0x;
+   ref.r = 0x;
+   ref.g = 0x;
+   ref.b = 0x;
+
+   memcpy(, , sizeof(out));
+   apply_3x4_matrix(, _matrix_3x4_50_desat);
+
+   KUNIT_EXPECT_MEMEQ(test, , , sizeof(out));
+
+   /* full black */
+   ref.a = 0x;
+   ref.r = 0x0;
+   ref.g = 0x0;
+   ref.b = 0x0;
+
+   memcpy(, , sizeof(out));
+   apply_3x4_matrix(, _matrix_3x4_50_desat);
+
+   KUNIT_EXPECT_MEMEQ(test, , , sizeof(out));
+
+   /* 50% grey */
+   ref.a = 0x;
+   ref.r = 0x8000;
+   ref.g = 0x8000;
+   ref.b = 0x8000;
+
+   memcpy(, , sizeof(out));
+   apply_3x4_matrix(, _matrix_3x4_50_desat);
+
+   KUNIT_EXPECT_MEMEQ(test, , , sizeof(out));
+
+   /* full red to 50% desat */
+   ref.a = 0x;
+   ref.r = 0x7fff;
+   ref.g = 0x3fff;
+   ref.b = 0x3fff;
+
+   out.a = 0x;
+   out.r = 0x;
+   out.g = 0x0;
+   out.b = 0x0;
+
+   apply_3x4_matrix(, _matrix_3x4_50_desat);
+
+   KUNIT_EXPECT_MEMEQ(test, , , sizeof(out));
+}
+
+/*
+ * BT.709 encoding matrix
+ *
+ * Values printed from within IGT when converting
+ * igt_matrix_3x4_bt709_enc to the fixed-point format expected
+ * by DRM/KMS.
+ */
+const struct drm_color_ctm_3x4 test_matrix_3x4_bt709_enc = { {
+   0x366cf400ull, 0xb7175900ull, 0x000127bb300ull, 0,
+   0x80001993b3a0ull, 0x80005609fe80ull, 0x6f9db200ull, 0,
+   0x9d70a400ull, 0x80008f011100ull, 0x8e6f9330ull, 0
+} };
+
+static void vkms_color_ctm_3x4_bt709(struct kunit *test)
+{
+   struct pixel_argb_s32 out;
+
+   /* full white to bt709 */
+   out.a = 0x;
+   out.r = 0x;
+   out.g = 0x;
+   out.b = 0x;
+
+   apply_3x4_matrix(, _matrix_3x4_bt709_enc);
+
+   /* Y 255 */
+   KUNIT_EXPECT_GT(test, out.r, 0xfe00);
+   KUNIT_EXPECT_LT(test, out.r, 0x1);
+
+   /* U 0 */
+   KUNIT_EXPECT_LT(test, out.g, 0x0100);
+
+   /* V 0 */
+   KUNIT_EXPECT_LT(test, out.b, 0x0100);
+
+   /* full black to bt709 */
+   out.a = 0x;
+   out.r = 0x0;
+   out.g = 0x0;
+   out.b = 0x0;
+
+   apply_3x4_matrix(, _matrix_3x4_bt709_enc);
+
+   /* Y 0 */
+   KUNIT_EXPECT_LT(test, out.r, 0x100);
+
+   /* U 0 */
+   KUNIT_EXPECT_LT(test, out.g, 0x0100);
+
+   /* V 0 */
+   KUNIT_EXPECT_LT(test, out.b, 0x0100);
+
+   /* gray to bt709 */
+   out.a = 0x;
+   out.r = 0x7fff;
+   out.g = 0x7fff;
+   out.b = 0x7fff;
+
+   apply_3x4_matrix(, _matrix_3x4_bt709_enc);
+
+   /* Y 127 */
+   KUNIT_EXPECT_GT(test, out.r, 0x7e00);
+   KUNIT_EXPECT_LT(test, out.r, 0x8000);
+
+   /* U 0 */
+   KUNIT_EXPECT_LT(test, out.g, 0x0100);
+
+   /* V 0 */
+   KUNIT_EXPECT_LT(test, out.b, 0x0100);
+
+   /* == red 255 - bt709 enc == */
+   out.a = 0x;
+   out.r = 0x;
+   out.g = 0x0;
+   out.b = 0x0;
+
+   apply_3x4_matrix(, _matrix_3x4_bt709_enc);
+
+   /* Y 54 */
+   KUNIT_EXPECT_GT(test, out.r, 0x3500);
+   KUNIT_EXPECT_LT(test, out.r, 0x3700);
+
+   /* U 0 */
+   KUNIT_EXPECT_LT(test, out.g, 0x0100);
+
+   /* V 157 */
+   KUNIT_EXPECT_GT(test, out.b, 0x9C00);
+   KUNIT_EXPECT_LT(test, out.b, 0x9E00);
+
+
+   /* == green 255 - bt709 enc == */
+   out.a = 0x;
+   out.r = 0x0;
+  

[RFC PATCH v4 26/42] drm/colorop: pass plane_color_pipeline client cap to atomic check

2024-02-26 Thread Harry Wentland
Drivers will need to know whether an atomic check/commit
originated from a client with DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE
so they can ignore deprecated properties, like COLOR_ENCODING
and COLOR_RANGE.

Pass the plane_color_pipeline bit to drm_atomic_state.

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/drm_atomic_uapi.c |  1 +
 include/drm/drm_atomic.h  | 17 +
 2 files changed, 18 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index 23b248987a7c..c7c1c614b0d9 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -1571,6 +1571,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
drm_modeset_acquire_init(, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
state->acquire_ctx = 
state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
+   state->plane_color_pipeline = file_priv->plane_color_pipeline;
 
 retry:
copied_objs = 0;
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 2346f19eda9f..61e6b5553eec 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -404,6 +404,23 @@ struct drm_atomic_state {
 * states.
 */
bool duplicated : 1;
+
+   /**
+* @plane_color_pipeline : 1
+*
+* Indicates whether this atomic state originated with a client that
+* set the DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE.
+*
+* Drivers and helper functions should use this to ignore legacy
+* properties that are incompatible with the drm_plane COLOR_PIPELINE
+* behavior, such as
+*  - COLOR_RANGE
+*  - COLOR_ENCODING
+* or any other driver-specific properties that might affect pixel
+* values.
+*/
+   bool plane_color_pipeline : 1;
+
struct __drm_colorops_state *colorops;
struct __drm_planes_state *planes;
struct __drm_crtcs_state *crtcs;
-- 
2.44.0



[RFC PATCH v4 35/42] drm/amd/display: Enable support for PQ 125 EOTF and Inverse

2024-02-26 Thread Harry Wentland
This patchset enables support for the PQ_125 EOTF and its inverse
on all existing plane 1D curve colorops, i.e., on DEGAM, SHAPER,
and BLND blocks.

With this patchset the following IGT subtests are passing:
kms_colorop --run plane-XR30-XR30-pq_125_eotf
kms_colorop --run plane-XR30-XR30-pq_125_inv_eotf
kms_colorop --run plane-XR30-XR30-pq_125_eotf-pq_125_inv_eotf
kms_colorop --run plane-XR30-XR30-pq_125_eotf-pq_125_inv_eotf-pq_125_eotf

Signed-off-by: Harry Wentland 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 20 +--
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c |  8 +---
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 3e3ae2b58b06..20b7eb47388c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -25,6 +25,7 @@
 #include "amdgpu.h"
 #include "amdgpu_mode.h"
 #include "amdgpu_dm.h"
+#include "amdgpu_dm_colorop.h"
 #include "dc.h"
 #include "modules/color/color_gamma.h"
 #include "basics/conversion.h"
@@ -676,6 +677,9 @@ amdgpu_colorop_tf_to_dc_tf(enum drm_colorop_curve_1d_type 
tf)
case DRM_COLOROP_1D_CURVE_SRGB_EOTF:
case DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF:
return TRANSFER_FUNCTION_SRGB;
+   case DRM_COLOROP_1D_CURVE_PQ_125_EOTF:
+   case DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF:
+   return TRANSFER_FUNCTION_PQ;
default:
return TRANSFER_FUNCTION_LINEAR;;
}
@@ -1158,8 +1162,10 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state 
*dc_plane_state,
struct drm_colorop *colorop = colorop_state->colorop;
struct drm_device *drm = colorop->dev;
 
-   if (colorop->type != DRM_COLOROP_1D_CURVE &&
-   colorop_state->curve_1d_type != DRM_COLOROP_1D_CURVE_SRGB_EOTF)
+   if (colorop->type != DRM_COLOROP_1D_CURVE)
+   return -EINVAL;
+
+   if (!(BIT(colorop_state->curve_1d_type) & 
amdgpu_dm_supported_degam_tfs))
return -EINVAL;
 
if (colorop_state->bypass) {
@@ -1191,7 +1197,7 @@ __set_dm_plane_colorop_degamma(struct drm_plane_state 
*plane_state,
/* 1st op: 1d curve - degamma */
for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
if (new_colorop_state->colorop == old_colorop &&
-   new_colorop_state->curve_1d_type == 
DRM_COLOROP_1D_CURVE_SRGB_EOTF) {
+   (BIT(new_colorop_state->curve_1d_type) & 
amdgpu_dm_supported_degam_tfs)) {
colorop_state = new_colorop_state;
break;
}
@@ -1213,8 +1219,10 @@ __set_colorop_in_shaper_1d_curve(struct dc_plane_state 
*dc_plane_state,
const struct drm_color_lut *shaper_lut;
uint32_t shaper_size;
 
-   if (colorop->type != DRM_COLOROP_1D_CURVE &&
-   colorop_state->curve_1d_type != DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF)
+   if (colorop->type != DRM_COLOROP_1D_CURVE)
+   return -EINVAL;
+
+   if (!(BIT(colorop_state->curve_1d_type) & 
amdgpu_dm_supported_shaper_tfs))
return -EINVAL;
 
if (colorop_state->bypass) {
@@ -1250,7 +1258,7 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state 
*plane_state,
/* 2nd op: 1d curve - shaper */
for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
if (new_colorop_state->colorop == old_colorop &&
-   new_colorop_state->curve_1d_type == 
DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF) {
+   (BIT(new_colorop_state->curve_1d_type) & 
amdgpu_dm_supported_shaper_tfs)) {
colorop_state = new_colorop_state;
break;
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index 449a2ad6a184..f99d8e09d89b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -32,10 +32,12 @@
 #include "amdgpu_dm_colorop.h"
 
 const u64 amdgpu_dm_supported_degam_tfs =
-   BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF);
+   BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
+   BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF);
 
- const u64 amdgpu_dm_supported_shaper_tfs =
-   BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF);
+const u64 amdgpu_dm_supported_shaper_tfs =
+   BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF) |
+   BIT(DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF);
 
 const u64 amdgpu_dm_supported_blnd_tfs =
BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF);
-- 
2.44.0



[RFC PATCH v4 28/42] drm/amd/display: Ignore deprecated props when plane_color_pipeline set

2024-02-26 Thread Harry Wentland
When the plane_color_pipeline bit is set we should ignore
deprecated properties, such as COLOR_RANGE and COLOR_ENCODING.

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index f6575d7dee97..47c6fd33fd60 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4948,6 +4948,10 @@ fill_plane_color_attributes(const struct drm_plane_state 
*plane_state,
 
*color_space = COLOR_SPACE_SRGB;
 
+   /* Ignore properties when DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set */
+   if (plane_state->state && plane_state->state->plane_color_pipeline)
+   return 0;
+
/* DRM color properties only affect non-RGB formats. */
if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
return 0;
-- 
2.44.0



[RFC PATCH v4 17/42] drm/vkms: Add enumerated 1D curve colorop

2024-02-26 Thread Harry Wentland
This patch introduces a VKMS color pipeline that includes two
drm_colorops for named transfer functions. For now the only ones
supported are sRGB EOTF, sRGB Inverse EOTF, and a Linear TF.
We will expand this in the future but I don't want to do so
without accompanying IGT tests.

We introduce a new vkms_luts.c file that hard-codes sRGB EOTF,
sRGB Inverse EOTF, and a linear EOTF LUT. These have been
generated with 256 entries each as IGT is currently testing
only 8 bpc surfaces. We will likely need higher precision
but I'm reluctant to make that change without clear indication
that we need it. We'll revisit and, if necessary, regenerate
the LUTs when we have IGT tests for higher precision buffers.

v4:
 - Drop _tf_ from color_pipeline init function
 - Pass supported TFs into colorop init
 - Create bypass pipeline in DRM helper (Pekka)

v2:
 - Add commit description
 - Fix sRGB EOTF LUT definition
 - Add linear and sRGB inverse EOTF LUTs

Signed-off-by: Harry Wentland 
Signed-off-by: Alex Hung 
---
 drivers/gpu/drm/vkms/Makefile|   4 +-
 drivers/gpu/drm/vkms/vkms_colorop.c  |  70 +++
 drivers/gpu/drm/vkms/vkms_composer.c |  45 ++
 drivers/gpu/drm/vkms/vkms_drv.h  |   4 +
 drivers/gpu/drm/vkms/vkms_luts.c | 802 +++
 drivers/gpu/drm/vkms/vkms_luts.h |  12 +
 drivers/gpu/drm/vkms/vkms_plane.c|   2 +
 7 files changed, 938 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/vkms/vkms_colorop.c
 create mode 100644 drivers/gpu/drm/vkms/vkms_luts.c
 create mode 100644 drivers/gpu/drm/vkms/vkms_luts.h

diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile
index 1b28a6a32948..c38455c46be4 100644
--- a/drivers/gpu/drm/vkms/Makefile
+++ b/drivers/gpu/drm/vkms/Makefile
@@ -6,6 +6,8 @@ vkms-y := \
vkms_formats.o \
vkms_crtc.o \
vkms_composer.o \
-   vkms_writeback.o
+   vkms_writeback.o \
+   vkms_colorop.o \
+   vkms_luts.o
 
 obj-$(CONFIG_DRM_VKMS) += vkms.o
diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c 
b/drivers/gpu/drm/vkms/vkms_colorop.c
new file mode 100644
index ..d2db366da6d3
--- /dev/null
+++ b/drivers/gpu/drm/vkms/vkms_colorop.c
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_COLOR_PIPELINES 5
+
+static const u64 supported_tfs =
+   BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
+   BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF);
+
+const int vkms_initialize_color_pipeline(struct drm_plane *plane, struct 
drm_prop_enum_list *list)
+{
+
+   struct drm_colorop *op, *prev_op;
+   struct drm_device *dev = plane->dev;
+   int ret;
+
+   /* 1st op: 1d curve */
+   op = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+   if (!op) {
+   DRM_ERROR("KMS: Failed to allocate colorop\n");
+   return -ENOMEM;
+   }
+
+   ret = drm_colorop_curve_1d_init(dev, op, plane, supported_tfs);
+   if (ret)
+   return ret;
+
+   list->type = op->base.id;
+   list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", op->base.id);
+
+   prev_op = op;
+
+   /* 2nd op: 1d curve */
+   op = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+   if (!op) {
+   DRM_ERROR("KMS: Failed to allocate colorop\n");
+   return -ENOMEM;
+   }
+
+   ret = drm_colorop_curve_1d_init(dev, op, plane, supported_tfs);
+   if (ret)
+   return ret;
+
+   drm_colorop_set_next_property(prev_op, op);
+
+   return 0;
+}
+
+int vkms_initialize_colorops(struct drm_plane *plane)
+{
+   struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
+   int len = 0;
+   int ret;
+
+   /* Add color pipeline */
+   ret = vkms_initialize_color_pipeline(plane, &(pipelines[len]));
+   if (ret)
+   return ret;
+   len++;
+
+   /* Create COLOR_PIPELINE property and attach */
+   drm_plane_create_color_pipeline_property(plane, pipelines, len);
+
+   return 0;
+}
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index b90e446d5954..9493bdb1ba3f 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -12,6 +12,7 @@
 #include 
 
 #include "vkms_drv.h"
+#include "vkms_luts.h"
 
 static u16 pre_mul_blend_channel(u16 src, u16 dst, u16 alpha)
 {
@@ -163,6 +164,47 @@ static void apply_lut(const struct vkms_crtc_state 
*crtc_state, struct line_buff
}
 }
 
+static void pre_blend_color_transform(const struct vkms_plane_state 
*plane_state, struct line_buffer *output_buffer)
+{
+   struct drm_colorop *colorop = plane_state->base.base.color_pipeline;
+
+   while (colorop) {
+   struct drm_colorop_state *colorop_state;
+
+   if (!colorop)
+   return;
+
+   /* TODO this is probably wrong */
+   colorop_state = colorop->state;
+
+  

[RFC PATCH v4 27/42] drm/colorop: define a new macro for_each_new_colorop_in_state

2024-02-26 Thread Harry Wentland
From: Alex Hung 

Create a new macro for_each_new_colorop_in_state to access new
drm_colorop_state updated from uapi.

Signed-off-by: Alex Hung 
---
 include/drm/drm_atomic.h | 20 
 1 file changed, 20 insertions(+)

diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 61e6b5553eec..a4c5ff99a515 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -979,6 +979,26 @@ void drm_state_dump(struct drm_device *dev, struct 
drm_printer *p);
  (new_colorop_state) = 
(__state)->colorops[__i].new_state, 1))
 
 
+/**
+ * for_each_new_colorop_in_state - iterate over all colorops in an atomic 
update
+ * @__state:  drm_atomic_state pointer
+ * @colorop:  drm_colorop iteration cursor
+ * @new_colorop_state:  drm_colorop_state iteration cursor for the new 
state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all colorops in an atomic update, tracking new state. 
This is
+ * useful is useful in places where the state delta needs to be considered, for
+ * example in atomic check functions.
+ */
+#define for_each_new_colorop_in_state(__state, colorop, new_colorop_state, 
__i) \
+   for ((__i) = 0; \
+(__i) < (__state)->dev->mode_config.num_colorop;   \
+(__i)++)   \
+   for_each_if ((__state)->colorops[__i].ptr &&\
+((colorop) = (__state)->colorops[__i].ptr, \
+ (void)(colorop) /* Only to avoid 
unused-but-set-variable warning */, \
+ (new_colorop_state) = 
(__state)->colorops[__i].new_state, 1))
+
 /**
  * for_each_oldnew_plane_in_state - iterate over all planes in an atomic update
  * @__state:  drm_atomic_state pointer
-- 
2.44.0



[RFC PATCH v4 24/42] drm/tests: Add a few tests around drm_fixed.h

2024-02-26 Thread Harry Wentland
While working on the CTM implementation of VKMS I had to ascertain
myself of a few assumptions. One of those is whether drm_fixed.h
treats its numbers using signed-magnitude or twos-complement. It is
twos-complement.

In order to make someone else's day easier I am adding the
drm_test_int2fixp test that validates the above assumption.

I am also adding a test for the new sm2fixp function that converts
from a signed-magnitude fixed point to the twos-complement fixed
point.

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/tests/Makefile|  3 +-
 drivers/gpu/drm/tests/drm_fixp_test.c | 69 +++
 2 files changed, 71 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/tests/drm_fixp_test.c

diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
index d6183b3d7688..98468f7908dd 100644
--- a/drivers/gpu/drm/tests/Makefile
+++ b/drivers/gpu/drm/tests/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \
drm_modes_test.o \
drm_plane_helper_test.o \
drm_probe_helper_test.o \
-   drm_rect_test.o
+   drm_rect_test.o \
+   drm_fixp_test.o
 
 CFLAGS_drm_mm_test.o := $(DISABLE_STRUCTLEAK_PLUGIN)
diff --git a/drivers/gpu/drm/tests/drm_fixp_test.c 
b/drivers/gpu/drm/tests/drm_fixp_test.c
new file mode 100644
index ..f420f173ff66
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_fixp_test.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ */
+
+#include 
+#include 
+
+static void drm_test_sm2fixp(struct kunit *test)
+{
+   KUNIT_EXPECT_EQ(test, 0x7fffll, ((1LL << 63) - 1));
+
+   /* 1 */
+   KUNIT_EXPECT_EQ(test, drm_int2fixp(1), drm_sm2fixp(1ull << 
DRM_FIXED_POINT));
+
+   /* -1 */
+   KUNIT_EXPECT_EQ(test, drm_int2fixp(-1), drm_sm2fixp((1ull << 63) | 
(1ull << DRM_FIXED_POINT)));
+
+   /* 0.5 */
+   KUNIT_EXPECT_EQ(test, drm_fixp_from_fraction(1, 2), drm_sm2fixp(1ull << 
(DRM_FIXED_POINT - 1)));
+
+   /* -0.5 */
+   KUNIT_EXPECT_EQ(test, drm_fixp_from_fraction(-1, 2), drm_sm2fixp((1ull 
<< 63) | (1ull << (DRM_FIXED_POINT - 1;
+
+}
+
+static void drm_test_int2fixp(struct kunit *test)
+{
+   /* 1 */
+   KUNIT_EXPECT_EQ(test, 1ll << 32, drm_int2fixp(1));
+
+   /* -1 */
+   KUNIT_EXPECT_EQ(test, -(1ll << 32), drm_int2fixp(-1));
+
+   /* 1 + (-1) = 0 */
+   KUNIT_EXPECT_EQ(test, 0, drm_int2fixp(1) + drm_int2fixp(-1));
+
+   /* 1 / 2 */
+   KUNIT_EXPECT_EQ(test, 1ll << 31, drm_fixp_from_fraction(1, 2));
+
+   /* -0.5 */
+   KUNIT_EXPECT_EQ(test, -(1ll << 31), drm_fixp_from_fraction(-1, 2));
+
+   /* (1 / 2) + (-1) = 0.5 */
+   KUNIT_EXPECT_EQ(test, 1ll << 31, drm_fixp_from_fraction(-1, 2) + 
drm_int2fixp(1));
+
+   /* (1 / 2) - 1) = 0.5 */
+   KUNIT_EXPECT_EQ(test, -(1ll << 31), drm_fixp_from_fraction(1, 2) + 
drm_int2fixp(-1));
+
+   /* (1 / 2) - 1) = 0.5 */
+   KUNIT_EXPECT_EQ(test, -(1ll << 31), drm_fixp_from_fraction(1, 2) - 
drm_int2fixp(1));
+
+}
+
+static struct kunit_case drm_fixp_tests[] = {
+   KUNIT_CASE(drm_test_int2fixp),
+   KUNIT_CASE(drm_test_sm2fixp),
+   { }
+};
+
+static struct kunit_suite drm_rect_test_suite = {
+   .name = "drm_fixp",
+   .test_cases = drm_fixp_tests,
+};
+
+kunit_test_suite(drm_rect_test_suite);
+
+MODULE_AUTHOR("AMD");
+MODULE_LICENSE("GPL and additional rights");
\ No newline at end of file
-- 
2.44.0



[RFC PATCH v4 09/42] drm/colorop: Introduce new drm_colorop mode object

2024-02-26 Thread Harry Wentland
This patches introduces a new drm_colorop mode object. This
object represents color transformations and can be used to
define color pipelines.

We also introduce the drm_colorop_state here, as well as
various helpers and state tracking bits.

v4:
 - Drop IOCTL definitions (Pekka)
 - add missing declaration (Chaitanya Kumar Borah)

v3:
 - Drop TODO for lock (it's handled in drm_modeset_drop_locks)
   (Melissa)
 - Don't get plane state when getting colorop state
 - Make some functions static (kernel test robot)

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/Makefile|   1 +
 drivers/gpu/drm/drm_atomic.c|  70 
 drivers/gpu/drm/drm_atomic_helper.c |  12 +++
 drivers/gpu/drm/drm_atomic_uapi.c   |  48 +
 drivers/gpu/drm/drm_colorop.c   | 152 ++
 drivers/gpu/drm/drm_mode_config.c   |   7 ++
 include/drm/drm_atomic.h|  82 +++
 include/drm/drm_atomic_uapi.h   |   1 +
 include/drm/drm_colorop.h   | 158 
 include/drm/drm_mode_config.h   |  18 
 include/drm/drm_plane.h |   2 +
 include/uapi/drm/drm_mode.h |   1 +
 12 files changed, 552 insertions(+)
 create mode 100644 drivers/gpu/drm/drm_colorop.c
 create mode 100644 include/drm/drm_colorop.h

diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 104b42df2e95..4b14dcbb6117 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -16,6 +16,7 @@ drm-y := \
drm_client.o \
drm_client_modeset.o \
drm_color_mgmt.o \
+   drm_colorop.o \
drm_connector.o \
drm_crtc.o \
drm_displayid.o \
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index a91737adf8e7..62e87e6a9653 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -42,6 +42,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
@@ -108,6 +109,7 @@ void drm_atomic_state_default_release(struct 
drm_atomic_state *state)
kfree(state->connectors);
kfree(state->crtcs);
kfree(state->planes);
+   kfree(state->colorops);
kfree(state->private_objs);
 }
 EXPORT_SYMBOL(drm_atomic_state_default_release);
@@ -139,6 +141,10 @@ drm_atomic_state_init(struct drm_device *dev, struct 
drm_atomic_state *state)
sizeof(*state->planes), GFP_KERNEL);
if (!state->planes)
goto fail;
+   state->colorops = kcalloc(dev->mode_config.num_colorop,
+ sizeof(*state->colorops), GFP_KERNEL);
+   if (!state->colorops)
+   goto fail;
 
/*
 * Because drm_atomic_state can be committed asynchronously we need our
@@ -250,6 +256,20 @@ void drm_atomic_state_default_clear(struct 
drm_atomic_state *state)
state->planes[i].new_state = NULL;
}
 
+   for (i = 0; i < config->num_colorop; i++) {
+   struct drm_colorop *colorop = state->colorops[i].ptr;
+
+   if (!colorop)
+   continue;
+
+   drm_colorop_atomic_destroy_state(colorop,
+state->colorops[i].state);
+   state->colorops[i].ptr = NULL;
+   state->colorops[i].state = NULL;
+   state->colorops[i].old_state = NULL;
+   state->colorops[i].new_state = NULL;
+   }
+
for (i = 0; i < state->num_private_objs; i++) {
struct drm_private_obj *obj = state->private_objs[i].ptr;
 
@@ -571,6 +591,56 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_atomic_get_plane_state);
 
+
+/**
+ * drm_atomic_get_colorop_state - get colorop state
+ * @state: global atomic state object
+ * @colorop: colorop to get state object for
+ *
+ * This function returns the colorop state for the given colorop, allocating it
+ * if needed. It will also grab the relevant plane lock to make sure that the
+ * state is consistent.
+ *
+ * Returns:
+ *
+ * Either the allocated state or the error code encoded into the pointer. When
+ * the error is EDEADLK then the w/w mutex code has detected a deadlock and the
+ * entire atomic sequence must be restarted. All other errors are fatal.
+ */
+struct drm_colorop_state *
+drm_atomic_get_colorop_state(struct drm_atomic_state *state,
+struct drm_colorop *colorop)
+{
+   int ret, index = drm_colorop_index(colorop);
+   struct drm_colorop_state *colorop_state;
+
+   WARN_ON(!state->acquire_ctx);
+
+   colorop_state = drm_atomic_get_existing_colorop_state(state, colorop);
+   if (colorop_state)
+   return colorop_state;
+
+   ret = drm_modeset_lock(>plane->mutex, state->acquire_ctx);
+   if (ret)
+   return ERR_PTR(ret);
+
+   colorop_state = drm_atomic_helper_colorop_duplicate_state(colorop);

[RFC PATCH v4 15/42] drm/plane: Add COLOR PIPELINE property

2024-02-26 Thread Harry Wentland
We're adding a new enum COLOR PIPELINE property. This
property will have entries for each COLOR PIPELINE by
referencing the DRM object ID of the first drm_colorop
of the pipeline. 0 disables the entire COLOR PIPELINE.

Userspace can use this to discover the available color
pipelines, as well as set the desired one. The color
pipelines are programmed via properties on the actual
drm_colorop objects.

v4:
 - Add pipeline property creation helper (Pekka)
 - Fix function comment for
   drm_atomic_set_colorop_for_plane (Pekka)
 - Always create Bypass pipeline (Pekka)
 - Add missing function declaration (Chaitanya Kumar Borah)

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/drm_atomic.c  | 46 
 drivers/gpu/drm/drm_atomic_state_helper.c |  5 +++
 drivers/gpu/drm/drm_atomic_uapi.c | 42 ++
 drivers/gpu/drm/drm_plane.c   | 52 +++
 include/drm/drm_atomic.h  |  3 ++
 include/drm/drm_atomic_uapi.h |  2 +
 include/drm/drm_plane.h   | 11 +
 7 files changed, 161 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 3645c36d63b3..27a8805c5fa1 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1458,6 +1458,52 @@ drm_atomic_add_affected_planes(struct drm_atomic_state 
*state,
 }
 EXPORT_SYMBOL(drm_atomic_add_affected_planes);
 
+/**
+ * drm_atomic_add_affected_colorops - add colorops for plane
+ * @state: atomic state
+ * @plane: DRM plane
+ *
+ * This function walks the current configuration and adds all colorops
+ * currently used by @plane to the atomic configuration @state. This is useful
+ * when an atomic commit also needs to check all currently enabled colorop on
+ * @plane, e.g. when changing the mode. It's also useful when re-enabling a 
plane
+ * to avoid special code to force-enable all colorops.
+ *
+ * Since acquiring a colorop state will always also acquire the w/w mutex of 
the
+ * current plane for that colorop (if there is any) adding all the colorop 
states for
+ * a plane will not reduce parallelism of atomic updates.
+ *
+ * Returns:
+ * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
+ * then the w/w mutex code has detected a deadlock and the entire atomic
+ * sequence must be restarted. All other errors are fatal.
+ */
+int
+drm_atomic_add_affected_colorops(struct drm_atomic_state *state,
+struct drm_plane *plane)
+{
+   struct drm_colorop *colorop;
+   struct drm_colorop_state *colorop_state;
+
+   WARN_ON(!drm_atomic_get_new_plane_state(state, plane));
+
+   drm_dbg_atomic(plane->dev,
+  "Adding all current colorops for [plane:%d:%s] to %p\n",
+  plane->base.id, plane->name, state);
+
+   drm_for_each_colorop(colorop, plane->dev) {
+   if (colorop->plane != plane)
+   continue;
+
+   colorop_state = drm_atomic_get_colorop_state(state, colorop);
+   if (IS_ERR(colorop_state))
+   return PTR_ERR(colorop_state);
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_atomic_add_affected_colorops);
+
 /**
  * drm_atomic_check_only - check whether a given config would work
  * @state: atomic configuration to check
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
b/drivers/gpu/drm/drm_atomic_state_helper.c
index 519228eb1095..d1dd082b1286 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -267,6 +267,11 @@ void __drm_atomic_helper_plane_state_reset(struct 
drm_plane_state *plane_state,
plane_state->color_range = val;
}
 
+   if (plane->color_pipeline_property) {
+   /* default is always NULL, i.e., bypass */
+   plane_state->color_pipeline = NULL;
+   }
+
if (plane->zpos_property) {
if (!drm_object_property_get_default_value(>base,
   plane->zpos_property,
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index 87f00131be11..86f77a9aa3a8 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -256,6 +256,36 @@ drm_atomic_set_fb_for_plane(struct drm_plane_state 
*plane_state,
 }
 EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
 
+
+/**
+ * drm_atomic_set_colorop_for_plane - set colorop for plane
+ * @plane_state: atomic state object for the plane
+ * @colorop: colorop to use for the plane
+ *
+ * Helper function to select the color pipeline on a plane by setting
+ * it to the first drm_colorop element of the pipeline.
+ */
+void
+drm_atomic_set_colorop_for_plane(struct drm_plane_state *plane_state,
+struct drm_colorop *colorop)
+{
+   struct drm_plane *plane = plane_state->plane;
+
+   if (colorop)
+

[RFC PATCH v4 22/42] drm/vkms: Use s32 for internal color pipeline precision

2024-02-26 Thread Harry Wentland
Certain operations require us to preserve values below 0.0 and
above 1.0 (0x0 and 0x respectively in 16 bpc unorm). One
such operation is a BT709 encoding operation followed by its
decoding operation, or the reverse.

We'll use s32 values as intermediate in and outputs of our
color operations, for the operations where it matters.

For now this won't apply to LUT operations. We might want to
update those to work on s32 as well, but it's unclear how
that should work for unorm LUT definitions. We'll revisit
that once we add LUT + CTM tests.

In order to allow for this we'll also invert the nesting of our
colorop processing loops. We now use the pixel iteration loop
on the outside and the colorop iteration on the inside.

v4:
 - Clarify that we're packing 16-bit UNORM into s32, not
   converting values to a different representation (Pekka)

v3:
 - Use new colorop->next pointer

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/vkms/vkms_composer.c | 57 +---
 drivers/gpu/drm/vkms/vkms_drv.h  |  4 ++
 2 files changed, 48 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index 25b786b49db0..d2101fa55aa3 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -164,7 +164,7 @@ static void apply_lut(const struct vkms_crtc_state 
*crtc_state, struct line_buff
}
 }
 
-static void apply_colorop(struct pixel_argb_u16 *pixel, struct drm_colorop 
*colorop)
+static void apply_colorop(struct pixel_argb_s32 *pixel, struct drm_colorop 
*colorop)
 {
/* TODO is this right? */
struct drm_colorop_state *colorop_state = colorop->state;
@@ -191,25 +191,56 @@ static void apply_colorop(struct pixel_argb_u16 *pixel, 
struct drm_colorop *colo
 
 static void pre_blend_color_transform(const struct vkms_plane_state 
*plane_state, struct line_buffer *output_buffer)
 {
-   struct drm_colorop *colorop = plane_state->base.base.color_pipeline;
+   struct drm_colorop *colorop;
+   struct pixel_argb_s32 pixel;
 
-   while (colorop) {
-   struct drm_colorop_state *colorop_state;
+   for (size_t x = 0; x < output_buffer->n_pixels; x++) {
 
-   if (!colorop)
-   return;
+   /*
+* Some operations, such as applying a BT709 encoding matrix,
+* followed by a decoding matrix, require that we preserve
+* values above 1.0 and below 0.0 until the end of the pipeline.
+*
+* Pack the 16-bit UNORM values into s32 to give us head-room to
+* avoid clipping until we're at the end of the pipeline. Clip
+* intentionally at the end of the pipeline before packing
+* UNORM values back into u16.
+*/
+   pixel.a = output_buffer->pixels[x].a;
+   pixel.r = output_buffer->pixels[x].r;
+   pixel.g = output_buffer->pixels[x].g;
+   pixel.b = output_buffer->pixels[x].b;
 
-   /* TODO this is probably wrong */
-   colorop_state = colorop->state;
+   colorop = plane_state->base.base.color_pipeline;
+   while (colorop) {
+   struct drm_colorop_state *colorop_state;
 
-   if (!colorop_state)
-   return;
+   if (!colorop)
+   return;
+
+   /* TODO this is probably wrong */
+   colorop_state = colorop->state;
+
+   if (!colorop_state)
+   return;
 
-   for (size_t x = 0; x < output_buffer->n_pixels; x++)
if (!colorop_state->bypass)
-   apply_colorop(_buffer->pixels[x], 
colorop);
+   apply_colorop(, colorop);
 
-   colorop = colorop->next;
+   colorop = colorop->next;
+   }
+
+   /* clamp pixel */
+   pixel.a = max(min(pixel.a, 0x), 0x0);
+   pixel.r = max(min(pixel.r, 0x), 0x0);
+   pixel.g = max(min(pixel.g, 0x), 0x0);
+   pixel.b = max(min(pixel.b, 0x), 0x0);
+
+   /* put back to output_buffer */
+   output_buffer->pixels[x].a = pixel.a;
+   output_buffer->pixels[x].r = pixel.r;
+   output_buffer->pixels[x].g = pixel.g;
+   output_buffer->pixels[x].b = pixel.b;
}
 }
 
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index 2bcc24c196a2..fadb7685a360 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -36,6 +36,10 @@ struct vkms_frame_info {
unsigned int cpp;
 };
 
+struct pixel_argb_s32 {
+   s32 a, r, g, b;
+};
+
 struct pixel_argb_u16 {
u16 a, r, g, b;
 };

[RFC PATCH v4 21/42] drm/vkms: Pull apply_colorop out of pre_blend_color_transform

2024-02-26 Thread Harry Wentland
The if/switch statement is bound to grow with more types and
subtypes. Pull this out into its own funcion to make things more
manageable and readable.

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/vkms/vkms_composer.c | 48 
 1 file changed, 28 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index 9493bdb1ba3f..25b786b49db0 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -164,6 +164,31 @@ static void apply_lut(const struct vkms_crtc_state 
*crtc_state, struct line_buff
}
 }
 
+static void apply_colorop(struct pixel_argb_u16 *pixel, struct drm_colorop 
*colorop)
+{
+   /* TODO is this right? */
+   struct drm_colorop_state *colorop_state = colorop->state;
+
+   if (colorop->type == DRM_COLOROP_1D_CURVE) {
+   switch (colorop_state->curve_1d_type) {
+   case DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF:
+   pixel->r = 
apply_lut_to_channel_value(_inv_eotf, pixel->r, LUT_RED);
+   pixel->g = 
apply_lut_to_channel_value(_inv_eotf, pixel->g, LUT_GREEN);
+   pixel->b = 
apply_lut_to_channel_value(_inv_eotf, pixel->b, LUT_BLUE);
+   break;
+   case DRM_COLOROP_1D_CURVE_SRGB_EOTF:
+   pixel->r = 
apply_lut_to_channel_value(_eotf, pixel->r, LUT_RED);
+   pixel->g = 
apply_lut_to_channel_value(_eotf, pixel->g, LUT_GREEN);
+   pixel->b = 
apply_lut_to_channel_value(_eotf, pixel->b, LUT_BLUE);
+   break;
+   default:
+   DRM_DEBUG_DRIVER("unkown colorop 1D curve type 
%d\n", colorop_state->curve_1d_type);
+   break;
+   }
+   }
+
+}
+
 static void pre_blend_color_transform(const struct vkms_plane_state 
*plane_state, struct line_buffer *output_buffer)
 {
struct drm_colorop *colorop = plane_state->base.base.color_pipeline;
@@ -180,26 +205,9 @@ static void pre_blend_color_transform(const struct 
vkms_plane_state *plane_state
if (!colorop_state)
return;
 
-   for (size_t x = 0; x < output_buffer->n_pixels; x++) {
-   struct pixel_argb_u16 *pixel = 
_buffer->pixels[x];
-
-   if (colorop->type == DRM_COLOROP_1D_CURVE &&
-   colorop_state->bypass == false) {
-   switch (colorop_state->curve_1d_type) {
-   case DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF:
-   pixel->r = 
apply_lut_to_channel_value(_inv_eotf, pixel->r, LUT_RED);
-   pixel->g = 
apply_lut_to_channel_value(_inv_eotf, pixel->g, LUT_GREEN);
-   pixel->b = 
apply_lut_to_channel_value(_inv_eotf, pixel->b, LUT_BLUE);
-   break;
-   case DRM_COLOROP_1D_CURVE_SRGB_EOTF:
-   default:
-   pixel->r = 
apply_lut_to_channel_value(_eotf, pixel->r, LUT_RED);
-   pixel->g = 
apply_lut_to_channel_value(_eotf, pixel->g, LUT_GREEN);
-   pixel->b = 
apply_lut_to_channel_value(_eotf, pixel->b, LUT_BLUE);
-   break;
-   }
-   }
-   }
+   for (size_t x = 0; x < output_buffer->n_pixels; x++)
+   if (!colorop_state->bypass)
+   apply_colorop(_buffer->pixels[x], 
colorop);
 
colorop = colorop->next;
}
-- 
2.44.0



[RFC PATCH v4 01/42] drm: Don't treat 0 as -1 in drm_fixp2int_ceil

2024-02-26 Thread Harry Wentland
Unit testing this in VKMS shows that passing 0 into
this function returns -1, which is highly counter-
intuitive. Fix it by checking whether the input is
>= 0 instead of > 0.

Fixes: 64566b5e767f9 ("drm: Add drm_fixp_from_fraction and drm_fixp2int_ceil")
Signed-off-by: Harry Wentland 
Reviewed-by: Simon Ser 
Reviewed-by: Melissa Wen 
---
 include/drm/drm_fixed.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/drm/drm_fixed.h b/include/drm/drm_fixed.h
index 6ea339d5de08..0c9f917a4d4b 100644
--- a/include/drm/drm_fixed.h
+++ b/include/drm/drm_fixed.h
@@ -95,7 +95,7 @@ static inline int drm_fixp2int_round(s64 a)
 
 static inline int drm_fixp2int_ceil(s64 a)
 {
-   if (a > 0)
+   if (a >= 0)
return drm_fixp2int(a + DRM_FIXED_ALMOST_ONE);
else
return drm_fixp2int(a - DRM_FIXED_ALMOST_ONE);
-- 
2.44.0



[RFC PATCH v4 04/42] drm/vkms: Round fixp2int conversion in lerp_u16

2024-02-26 Thread Harry Wentland
fixp2int always rounds down, fixp2int_ceil rounds up. We need
the new fixp2int_round.

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/vkms/vkms_composer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index 3c99fb8b54e2..e70cd473e3be 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -98,7 +98,7 @@ static u16 lerp_u16(u16 a, u16 b, s64 t)
 
s64 delta = drm_fixp_mul(b_fp - a_fp,  t);
 
-   return drm_fixp2int(a_fp + delta);
+   return drm_fixp2int_round(a_fp + delta);
 }
 
 static s64 get_lut_index(const struct vkms_color_lut *lut, u16 channel_value)
-- 
2.44.0



[RFC PATCH v4 13/42] drm/colorop: Add NEXT property

2024-02-26 Thread Harry Wentland
We'll construct color pipelines out of drm_colorop by
chaining them via the NEXT pointer. NEXT will point to
the next drm_colorop in the pipeline, or by 0 if we're
at the end of the pipeline.

v4:
 - Allow setting of NEXT property to NULL (Chaitanya Kumar Borah)

v3:
 - Add next pointer to colorop to be used by drivers
   and in DRM core

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/drm_colorop.c | 29 +
 include/drm/drm_colorop.h | 20 
 2 files changed, 49 insertions(+)

diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 29979816a2d1..71c2286333a1 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -59,6 +59,7 @@ int drm_colorop_init(struct drm_device *dev, struct 
drm_colorop *colorop,
colorop->dev = dev;
colorop->type = type;
colorop->plane = plane;
+   colorop->next = NULL;
 
list_add_tail(>head, >colorop_list);
colorop->index = config->num_colorop++;
@@ -92,6 +93,15 @@ int drm_colorop_init(struct drm_device *dev, struct 
drm_colorop *colorop,
   colorop->bypass_property,
   1);
 
+   prop = drm_property_create_object(dev, DRM_MODE_PROP_IMMUTABLE | 
DRM_MODE_PROP_ATOMIC,
+ "NEXT", DRM_MODE_OBJECT_COLOROP);
+   if (!prop)
+   return -ENOMEM;
+   colorop->next_property = prop;
+   drm_object_attach_property(>base,
+  colorop->next_property,
+  0);
+
return ret;
 }
 EXPORT_SYMBOL(drm_colorop_init);
@@ -279,3 +289,22 @@ const char *drm_get_colorop_curve_1d_type_name(enum 
drm_colorop_curve_1d_type ty
 
return colorop_curve_1d_type_names[type];
 }
+
+/**
+ * drm_colorop_set_next_property - sets the next pointer
+ * @colorop: drm colorop
+ * @next: next colorop
+ *
+ * Should be used when constructing the color pipeline
+ */
+void drm_colorop_set_next_property(struct drm_colorop *colorop, struct 
drm_colorop *next)
+{
+   if (!colorop->next_property)
+   return;
+
+   drm_object_property_set_value(>base,
+ colorop->next_property,
+ next ? next->base.id : 0);
+   colorop->next = next;
+}
+EXPORT_SYMBOL(drm_colorop_set_next_property);
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index 28aa5c1c309e..8060988b5892 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -132,6 +132,14 @@ struct drm_colorop {
 */
enum drm_colorop_type type;
 
+   /**
+* @next:
+*
+* Read-only
+* Pointer to next drm_colorop in pipeline
+*/
+   struct drm_colorop *next;
+
/**
 * @type_property:
 *
@@ -159,10 +167,20 @@ struct drm_colorop {
 */
struct drm_property *curve_1d_type_property;
 
+   /**
+* @next_property
+*
+* Read-only property to next colorop in the pipeline
+*/
+   struct drm_property *next_property;
+
 };
 
 #define obj_to_colorop(x) container_of(x, struct drm_colorop, base)
 
+
+
+
 /**
  * drm_crtc_find - look up a Colorop object from its ID
  * @dev: DRM device
@@ -213,5 +231,7 @@ static inline unsigned int drm_colorop_index(const struct 
drm_colorop *colorop)
 #define drm_for_each_colorop(colorop, dev) \
list_for_each_entry(colorop, &(dev)->mode_config.colorop_list, head)
 
+void drm_colorop_set_next_property(struct drm_colorop *colorop, struct 
drm_colorop *next);
+
 
 #endif /* __DRM_COLOROP_H__ */
-- 
2.44.0



[RFC PATCH v4 14/42] drm/colorop: Add atomic state print for drm_colorop

2024-02-26 Thread Harry Wentland
Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/drm_atomic.c | 25 -
 include/drm/drm_colorop.h|  5 +
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index b400e32c9d39..3645c36d63b3 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -783,6 +783,19 @@ static int drm_atomic_plane_check(const struct 
drm_plane_state *old_plane_state,
return 0;
 }
 
+
+
+static void drm_atomic_colorop_print_state(struct drm_printer *p,
+   const struct drm_colorop_state *state)
+{
+   struct drm_colorop *colorop = state->colorop;
+
+   drm_printf(p, "colorop[%u]:\n", colorop->base.id);
+   drm_printf(p, "\ttype=%s\n", drm_get_colorop_type_name(colorop->type));
+   drm_printf(p, "\tbypass=%u\n", state->bypass);
+   drm_printf(p, "\tcurve_1d_type=%s\n", 
drm_get_colorop_curve_1d_type_name(state->curve_1d_type));
+}
+
 static void drm_atomic_plane_print_state(struct drm_printer *p,
const struct drm_plane_state *state)
 {
@@ -804,7 +817,8 @@ static void drm_atomic_plane_print_state(struct drm_printer 
*p,
drm_printf(p, "\tcolor-range=%s\n",
   drm_get_color_range_name(state->color_range));
drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed);
-
+   drm_printf(p, "\tcolor-pipeline=%d\n",
+  state->color_pipeline ? state->color_pipeline->base.id : 0);
if (plane->funcs->atomic_print_state)
plane->funcs->atomic_print_state(p, state);
 }
@@ -1840,6 +1854,7 @@ static void __drm_state_dump(struct drm_device *dev, 
struct drm_printer *p,
 bool take_locks)
 {
struct drm_mode_config *config = >mode_config;
+   struct drm_colorop *colorop;
struct drm_plane *plane;
struct drm_crtc *crtc;
struct drm_connector *connector;
@@ -1849,6 +1864,14 @@ static void __drm_state_dump(struct drm_device *dev, 
struct drm_printer *p,
if (!drm_drv_uses_atomic_modeset(dev))
return;
 
+   list_for_each_entry(colorop, >colorop_list, head) {
+   if (take_locks)
+   drm_modeset_lock(>plane->mutex, NULL);
+   drm_atomic_colorop_print_state(p, colorop->state);
+   if (take_locks)
+   drm_modeset_unlock(>plane->mutex);
+   }
+
list_for_each_entry(plane, >plane_list, head) {
if (take_locks)
drm_modeset_lock(>mutex, NULL);
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index 8060988b5892..fc9a28d138b8 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -231,6 +231,11 @@ static inline unsigned int drm_colorop_index(const struct 
drm_colorop *colorop)
 #define drm_for_each_colorop(colorop, dev) \
list_for_each_entry(colorop, &(dev)->mode_config.colorop_list, head)
 
+const char *drm_get_color_pipeline_name(struct drm_colorop *colorop);
+
+const char *drm_get_colorop_type_name(enum drm_colorop_type type);
+const char *drm_get_colorop_curve_1d_type_name(enum drm_colorop_curve_1d_type 
type);
+
 void drm_colorop_set_next_property(struct drm_colorop *colorop, struct 
drm_colorop *next);
 
 
-- 
2.44.0



[RFC PATCH v4 10/42] drm/colorop: Add TYPE property

2024-02-26 Thread Harry Wentland
Add a read-only TYPE property. The TYPE specifies the colorop
type, such as enumerated curve, 1D LUT, CTM, 3D LUT, PWL LUT,
etc.

v4:
 - Use enum property for TYPE (Pekka)

v3:
 - Make TYPE a range property
 - Move enum drm_colorop_type to uapi header
 - Fix drm_get_colorop_type_name description

For now we're only introducing an enumerated 1D LUT type to
illustrate the concept.

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/drm_atomic.c  |  4 +--
 drivers/gpu/drm/drm_atomic_uapi.c |  8 +-
 drivers/gpu/drm/drm_colorop.c | 44 ++-
 include/drm/drm_colorop.h | 17 +++-
 include/uapi/drm/drm_mode.h   |  4 +++
 5 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 62e87e6a9653..b400e32c9d39 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -634,8 +634,8 @@ drm_atomic_get_colorop_state(struct drm_atomic_state *state,
state->colorops[index].new_state = colorop_state;
colorop_state->state = state;
 
-   drm_dbg_atomic(colorop->dev, "Added [COLOROP:%d] %p state to %p\n",
-  colorop->base.id, colorop_state, state);
+   drm_dbg_atomic(colorop->dev, "Added [COLOROP:%d:%d] %p state to %p\n",
+  colorop->base.id, colorop->type, colorop_state, state);
 
return colorop_state;
 }
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index 1f9b6dfa8ca7..e3067c095c72 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -660,7 +660,13 @@ drm_atomic_colorop_get_property(struct drm_colorop 
*colorop,
const struct drm_colorop_state *state,
struct drm_property *property, uint64_t *val)
 {
-   return -EINVAL;
+   if (property == colorop->type_property) {
+   *val = colorop->type;
+   } else {
+   return -EINVAL;
+   }
+
+   return 0;
 }
 
 static int drm_atomic_set_writeback_fb_for_connector(
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index a295ab96aee1..3a07a8fe2842 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -32,12 +32,17 @@
 
 /* TODO big colorop doc, including properties, etc. */
 
+static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
+   { DRM_COLOROP_1D_CURVE, "1D Curve" },
+};
+
 /* Init Helpers */
 
 int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
-struct drm_plane *plane)
+struct drm_plane *plane, enum drm_colorop_type type)
 {
struct drm_mode_config *config = >mode_config;
+   struct drm_property *prop;
int ret = 0;
 
ret = drm_mode_object_add(dev, >base, DRM_MODE_OBJECT_COLOROP);
@@ -46,12 +51,29 @@ int drm_colorop_init(struct drm_device *dev, struct 
drm_colorop *colorop,
 
colorop->base.properties = >properties;
colorop->dev = dev;
+   colorop->type = type;
colorop->plane = plane;
 
list_add_tail(>head, >colorop_list);
colorop->index = config->num_colorop++;
 
/* add properties */
+
+   /* type */
+   prop = drm_property_create_enum(dev,
+   DRM_MODE_PROP_IMMUTABLE,
+   "TYPE", drm_colorop_type_enum_list,
+   ARRAY_SIZE(drm_colorop_type_enum_list));
+
+   if (!prop)
+   return -ENOMEM;
+
+   colorop->type_property = prop;
+
+   drm_object_attach_property(>base,
+  colorop->type_property,
+  colorop->type);
+
return ret;
 }
 EXPORT_SYMBOL(drm_colorop_init);
@@ -150,3 +172,23 @@ void drm_colorop_reset(struct drm_colorop *colorop)
__drm_colorop_reset(colorop, colorop->state);
 }
 EXPORT_SYMBOL(drm_colorop_reset);
+
+
+static const char * const colorop_type_name[] = {
+   [DRM_COLOROP_1D_CURVE] = "1D Curve",
+};
+
+/**
+ * drm_get_colorop_type_name - return a string for colorop type
+ * @type: colorop type to compute name of
+ *
+ * In contrast to the other drm_get_*_name functions this one here returns a
+ * const pointer and hence is threadsafe.
+ */
+const char *drm_get_colorop_type_name(enum drm_colorop_type type)
+{
+   if (WARN_ON(type >= ARRAY_SIZE(colorop_type_name)))
+   return "unknown";
+
+   return colorop_type_name[type];
+}
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index e611f830f986..cb98c55f8387 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -103,6 +103,21 @@ struct drm_colorop {
/** @properties: property tracking for this plane */
struct drm_object_properties properties;
 
+   /**
+* @type:
+*
+* Read-only
+* Type of color operation
+

[RFC PATCH v4 12/42] drm/colorop: Add BYPASS property

2024-02-26 Thread Harry Wentland
We want to be able to bypass each colorop at all times.
Introduce a new BYPASS boolean property for this.

Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/drm_atomic_uapi.c |  6 +-
 drivers/gpu/drm/drm_colorop.c | 16 
 include/drm/drm_colorop.h | 20 
 3 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index fdd540cfe24f..87f00131be11 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -648,7 +648,9 @@ static int drm_atomic_colorop_set_property(struct 
drm_colorop *colorop,
struct drm_colorop_state *state, struct drm_file *file_priv,
struct drm_property *property, uint64_t val)
 {
-   if (property == colorop->curve_1d_type_property) {
+   if (property == colorop->bypass_property) {
+   state->bypass = val;
+   } else if (property == colorop->curve_1d_type_property) {
state->curve_1d_type = val;
} else {
drm_dbg_atomic(colorop->dev,
@@ -668,6 +670,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
 {
if (property == colorop->type_property) {
*val = colorop->type;
+   } else if (property == colorop->bypass_property) {
+   *val = state->bypass;
} else if (property == colorop->curve_1d_type_property) {
*val = state->curve_1d_type;
} else {
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index f4740b6115d1..29979816a2d1 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -80,6 +80,18 @@ int drm_colorop_init(struct drm_device *dev, struct 
drm_colorop *colorop,
   colorop->type_property,
   colorop->type);
 
+   /* bypass */
+   /* TODO can we reuse the mode_config->active_prop? */
+   prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
+   "BYPASS");
+   if (!prop)
+   return -ENOMEM;
+
+   colorop->bypass_property = prop;
+   drm_object_attach_property(>base,
+  colorop->bypass_property,
+  1);
+
return ret;
 }
 EXPORT_SYMBOL(drm_colorop_init);
@@ -123,6 +135,7 @@ int drm_colorop_curve_1d_init(struct drm_device *dev, 
struct drm_colorop *coloro
/* initialize 1D curve only attribute */
prop = drm_property_create_enum(dev, DRM_MODE_PROP_ATOMIC, 
"CURVE_1D_TYPE",
enum_list, len);
+
if (!prop)
return -ENOMEM;
 
@@ -138,6 +151,8 @@ static void 
__drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colo
struct 
drm_colorop_state *state)
 {
memcpy(state, colorop->state, sizeof(*state));
+
+   state->bypass = true;
 }
 
 struct drm_colorop_state *
@@ -189,6 +204,7 @@ static void __drm_colorop_state_reset(struct 
drm_colorop_state *colorop_state,
  struct drm_colorop *colorop)
 {
colorop_state->colorop = colorop;
+   colorop_state->bypass = true;
 }
 
 /**
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index 539db900f16f..28aa5c1c309e 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -45,6 +45,14 @@ struct drm_colorop_state {
 
/* colorop properties */
 
+   /**
+* @bypass:
+*
+* True if colorop shall be bypassed. False if colorop is
+* enabled.
+*/
+   bool bypass;
+
/**
 * @curve_1d_type:
 *
@@ -132,6 +140,18 @@ struct drm_colorop {
 */
struct drm_property *type_property;
 
+   /**
+* @bypass_property:
+*
+* Boolean property to control enablement of the color
+* operation. Setting bypass to "true" shall always be supported
+* in order to allow compositors to quickly fall back to
+* alternate methods of color processing. This is important
+* since setting color operations can fail due to unique
+* HW constraints.
+*/
+   struct drm_property *bypass_property;
+
/**
 * @curve_1d_type:
 *
-- 
2.44.0



[RFC PATCH v4 05/42] drm/vkms: Create separate Kconfig file for VKMS

2024-02-26 Thread Harry Wentland
This aligns with most other DRM drivers and will allow
us to add new VKMS config options without polluting
the DRM Kconfig.

v3:
 - Change SPDX to GPL-2.0-only to match DRM KConfig
   SPDX (Simon)

Signed-off-by: Harry Wentland 
Reviewed-by: Simon Ser 
---
 drivers/gpu/drm/Kconfig  | 14 +-
 drivers/gpu/drm/vkms/Kconfig | 15 +++
 2 files changed, 16 insertions(+), 13 deletions(-)
 create mode 100644 drivers/gpu/drm/vkms/Kconfig

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 2520db0b776e..e3ea8793cb8a 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -289,19 +289,7 @@ config DRM_VGEM
  as used by Mesa's software renderer for enhanced performance.
  If M is selected the module will be called vgem.
 
-config DRM_VKMS
-   tristate "Virtual KMS (EXPERIMENTAL)"
-   depends on DRM && MMU
-   select DRM_KMS_HELPER
-   select DRM_GEM_SHMEM_HELPER
-   select CRC32
-   default n
-   help
- Virtual Kernel Mode-Setting (VKMS) is used for testing or for
- running GPU in a headless machines. Choose this option to get
- a VKMS.
-
- If M is selected the module will be called vkms.
+source "drivers/gpu/drm/vkms/Kconfig"
 
 source "drivers/gpu/drm/exynos/Kconfig"
 
diff --git a/drivers/gpu/drm/vkms/Kconfig b/drivers/gpu/drm/vkms/Kconfig
new file mode 100644
index ..b9ecdebecb0b
--- /dev/null
+++ b/drivers/gpu/drm/vkms/Kconfig
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config DRM_VKMS
+   tristate "Virtual KMS (EXPERIMENTAL)"
+   depends on DRM && MMU
+   select DRM_KMS_HELPER
+   select DRM_GEM_SHMEM_HELPER
+   select CRC32
+   default n
+   help
+ Virtual Kernel Mode-Setting (VKMS) is used for testing or for
+ running GPU in a headless machines. Choose this option to get
+ a VKMS.
+
+ If M is selected the module will be called vkms.
-- 
2.44.0



[RFC PATCH v4 18/42] drm/vkms: Add kunit tests for linear and sRGB LUTs

2024-02-26 Thread Harry Wentland
Signed-off-by: Harry Wentland 
---
 drivers/gpu/drm/vkms/tests/vkms_color_tests.c | 37 ++-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vkms/tests/vkms_color_tests.c 
b/drivers/gpu/drm/vkms/tests/vkms_color_tests.c
index fc73e48aa57c..e6ac01dee830 100644
--- a/drivers/gpu/drm/vkms/tests/vkms_color_tests.c
+++ b/drivers/gpu/drm/vkms/tests/vkms_color_tests.c
@@ -31,7 +31,6 @@ const struct vkms_color_lut test_linear_lut = {
.channel_value2index_ratio = 0xf000fll
 };
 
-
 static void vkms_color_test_get_lut_index(struct kunit *test)
 {
int i;
@@ -40,6 +39,19 @@ static void vkms_color_test_get_lut_index(struct kunit *test)
 
for (i = 0; i < TEST_LUT_SIZE; i++)
KUNIT_EXPECT_EQ(test, 
drm_fixp2int_ceil(get_lut_index(_linear_lut, test_linear_array[i].red)), 
i);
+
+   KUNIT_EXPECT_EQ(test, drm_fixp2int(get_lut_index(_eotf, 0x0)), 
0x0);
+   KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(_eotf, 
0x0)), 0x0);
+   KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(_eotf, 
0x101)), 0x1);
+   KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(_eotf, 
0x202)), 0x2);
+
+   KUNIT_EXPECT_EQ(test, drm_fixp2int(get_lut_index(_inv_eotf, 0x0)), 
0x0);
+   KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(_inv_eotf, 
0x0)), 0x0);
+   KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(_inv_eotf, 
0x101)), 0x1);
+   KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(_inv_eotf, 
0x202)), 0x2);
+
+   KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(_eotf, 
0xfefe)), 0xfe);
+   KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(_eotf, 
0x)), 0xff);
 }
 
 static void vkms_color_test_lerp(struct kunit *test)
@@ -148,9 +160,32 @@ static void vkms_color_test_lerp(struct kunit *test)
KUNIT_EXPECT_EQ(test, lerp_u16(0x0, 0x1, 0x8000), 0x1);
 }
 
+static void vkms_color_test_linear(struct kunit *test)
+{
+   for (int i = 0; i < LUT_SIZE; i++) {
+   int linear = apply_lut_to_channel_value(_eotf, i * 
0x101, LUT_RED);
+   KUNIT_EXPECT_EQ(test, DIV_ROUND_CLOSEST(linear, 0x101), i);
+   }
+}
+
+static void vkms_color_srgb_inv_srgb(struct kunit *test)
+{
+   u16 srgb, final;
+
+   for (int i = 0; i < LUT_SIZE; i++) {
+   srgb = apply_lut_to_channel_value(_eotf, i * 0x101, 
LUT_RED);
+   final = apply_lut_to_channel_value(_inv_eotf, srgb, 
LUT_RED);
+
+   KUNIT_EXPECT_GE(test, final / 0x101, i-1);
+   KUNIT_EXPECT_LE(test, final / 0x101, i+1);
+   }
+}
+
 static struct kunit_case vkms_color_test_cases[] = {
KUNIT_CASE(vkms_color_test_get_lut_index),
KUNIT_CASE(vkms_color_test_lerp),
+   KUNIT_CASE(vkms_color_test_linear),
+   KUNIT_CASE(vkms_color_srgb_inv_srgb),
{}
 };
 
-- 
2.44.0



[RFC PATCH v4 07/42] drm/vkms: Avoid reading beyond LUT array

2024-02-26 Thread Harry Wentland
When the floor LUT index (drm_fixp2int(lut_index) is the last
index of the array the ceil LUT index will point to an entry
beyond the array. Make sure we guard against it and use the
value of the floor LUT index.

v3:
 - Drop bits from commit description that didn't contribute
   anything of value

Fixes: db1f254f2cfaf ("drm/vkms: Add support to 1D gamma LUT")
Signed-off-by: Harry Wentland 
Cc: Arthur Grillo 
Reviewed-by: Melissa Wen 
---
 drivers/gpu/drm/vkms/vkms_composer.c | 14 ++
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index d178f2a400f6..b90e446d5954 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -123,6 +123,8 @@ static u16 apply_lut_to_channel_value(const struct 
vkms_color_lut *lut, u16 chan
  enum lut_channel channel)
 {
s64 lut_index = get_lut_index(lut, channel_value);
+   u16 *floor_lut_value, *ceil_lut_value;
+   u16 floor_channel_value, ceil_channel_value;
 
/*
 * This checks if `struct drm_color_lut` has any gap added by the 
compiler
@@ -130,11 +132,15 @@ static u16 apply_lut_to_channel_value(const struct 
vkms_color_lut *lut, u16 chan
 */
static_assert(sizeof(struct drm_color_lut) == sizeof(__u16) * 4);
 
-   u16 *floor_lut_value = (__u16 *)>base[drm_fixp2int(lut_index)];
-   u16 *ceil_lut_value = (__u16 *)>base[drm_fixp2int_ceil(lut_index)];
+   floor_lut_value = (__u16 *)>base[drm_fixp2int(lut_index)];
+   if (drm_fixp2int(lut_index) == (lut->lut_length - 1))
+   /* We're at the end of the LUT array, use same value for ceil 
and floor */
+   ceil_lut_value = floor_lut_value;
+   else
+   ceil_lut_value = (__u16 
*)>base[drm_fixp2int_ceil(lut_index)];
 
-   u16 floor_channel_value = floor_lut_value[channel];
-   u16 ceil_channel_value = ceil_lut_value[channel];
+   floor_channel_value = floor_lut_value[channel];
+   ceil_channel_value = ceil_lut_value[channel];
 
return lerp_u16(floor_channel_value, ceil_channel_value,
lut_index & DRM_FIXED_DECIMAL_MASK);
-- 
2.44.0



[RFC PATCH v4 06/42] drm/vkms: Add kunit tests for VKMS LUT handling

2024-02-26 Thread Harry Wentland
Debugging LUT math is much easier when we can unit test
it. Add kunit functionality to VKMS and add tests for
 - get_lut_index
 - lerp_u16

v4:
 - Test the critical points of the lerp function (Pekka)

v3:
 - Use include way of testing static functions (Arthur)

Signed-off-by: Harry Wentland 
Cc: Arthur Grillo 
---
 drivers/gpu/drm/vkms/Kconfig  |   5 +
 drivers/gpu/drm/vkms/tests/.kunitconfig   |   4 +
 drivers/gpu/drm/vkms/tests/vkms_color_tests.c | 163 ++
 drivers/gpu/drm/vkms/vkms_composer.c  |   8 +-
 4 files changed, 178 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/vkms/tests/.kunitconfig
 create mode 100644 drivers/gpu/drm/vkms/tests/vkms_color_tests.c

diff --git a/drivers/gpu/drm/vkms/Kconfig b/drivers/gpu/drm/vkms/Kconfig
index b9ecdebecb0b..c1f8b343ff0e 100644
--- a/drivers/gpu/drm/vkms/Kconfig
+++ b/drivers/gpu/drm/vkms/Kconfig
@@ -13,3 +13,8 @@ config DRM_VKMS
  a VKMS.
 
  If M is selected the module will be called vkms.
+
+config DRM_VKMS_KUNIT_TESTS
+   tristate "Tests for VKMS" if !KUNIT_ALL_TESTS
+   depends on DRM_VKMS && KUNIT
+   default KUNIT_ALL_TESTS
diff --git a/drivers/gpu/drm/vkms/tests/.kunitconfig 
b/drivers/gpu/drm/vkms/tests/.kunitconfig
new file mode 100644
index ..70e378228cbd
--- /dev/null
+++ b/drivers/gpu/drm/vkms/tests/.kunitconfig
@@ -0,0 +1,4 @@
+CONFIG_KUNIT=y
+CONFIG_DRM=y
+CONFIG_DRM_VKMS=y
+CONFIG_DRM_VKMS_KUNIT_TESTS=y
diff --git a/drivers/gpu/drm/vkms/tests/vkms_color_tests.c 
b/drivers/gpu/drm/vkms/tests/vkms_color_tests.c
new file mode 100644
index ..fc73e48aa57c
--- /dev/null
+++ b/drivers/gpu/drm/vkms/tests/vkms_color_tests.c
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#include 
+
+#include 
+
+#define TEST_LUT_SIZE 16
+
+static struct drm_color_lut test_linear_array[TEST_LUT_SIZE] = {
+   { 0x0, 0x0, 0x0, 0 },
+   { 0x, 0x, 0x, 0 },
+   { 0x, 0x, 0x, 0 },
+   { 0x, 0x, 0x, 0 },
+   { 0x, 0x, 0x, 0 },
+   { 0x, 0x, 0x, 0 },
+   { 0x, 0x, 0x, 0 },
+   { 0x, 0x, 0x, 0 },
+   { 0x, 0x, 0x, 0 },
+   { 0x, 0x, 0x, 0 },
+   { 0x, 0x, 0x, 0 },
+   { 0x, 0x, 0x, 0 },
+   { 0x, 0x, 0x, 0 },
+   { 0x, 0x, 0x, 0 },
+   { 0x, 0x, 0x, 0 },
+   { 0x, 0x, 0x, 0 },
+};
+
+const struct vkms_color_lut test_linear_lut = {
+   .base = test_linear_array,
+   .lut_length = TEST_LUT_SIZE,
+   .channel_value2index_ratio = 0xf000fll
+};
+
+
+static void vkms_color_test_get_lut_index(struct kunit *test)
+{
+   int i;
+
+   KUNIT_EXPECT_EQ(test, drm_fixp2int(get_lut_index(_linear_lut, 
test_linear_array[0].red)), 0);
+
+   for (i = 0; i < TEST_LUT_SIZE; i++)
+   KUNIT_EXPECT_EQ(test, 
drm_fixp2int_ceil(get_lut_index(_linear_lut, test_linear_array[i].red)), 
i);
+}
+
+static void vkms_color_test_lerp(struct kunit *test)
+{
+   /*** half-way round down ***/
+   s64 t = 0x8000 - 1;
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x0, 0x10, t), 0x8);
+
+   /* odd a */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0x10, t), 0x8);
+
+   /* odd b */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0xf, t), 0x8);
+
+   /* b = a */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x10, t), 0x10);
+
+   /* b = a + 1 */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x11, t), 0x10);
+
+
+   /*** half-way round up ***/
+   t = 0x8000;
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x0, 0x10, t), 0x8);
+
+   /* odd a */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0x10, t), 0x9);
+
+   /* odd b */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0xf, t), 0x8);
+
+   /* b = a */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x10, t), 0x10);
+
+   /* b = a + 1 */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x11, t), 0x11);
+
+   /*** t = 0.0 ***/
+   t = 0x0;
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x0, 0x10, t), 0x0);
+
+   /* odd a */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0x10, t), 0x1);
+
+   /* odd b */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0xf, t), 0x1);
+
+   /* b = a */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x10, t), 0x10);
+
+   /* b = a + 1 */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x11, t), 0x10);
+
+   /*** t = 1.0 ***/
+   t = 0x1;
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x0, 0x10, t), 0x10);
+
+   /* odd a */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0x10, t), 0x10);
+
+   /* odd b */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0xf, t), 0xf);
+
+   /* b = a */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x10, t), 0x10);
+
+   /* b = a + 1 */
+   KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x11, t), 0x11);
+
+
+   /*** t = 0.0 + 1 ***/
+   t = 0x0 + 1;
+   

[RFC PATCH v4 03/42] drm: Correctly round for fixp2int_round

2024-02-26 Thread Harry Wentland
A value of 0x8000 and higher should round up, and
below should round down. VKMS Kunit tests for lerp_u16
showed that this is not the case. Fix it.

1 << (DRM_FIXED_POINT_HALF - 1) =
1 << 15 = 0x8000

This is not 0.5, but 0.0762939453125.

Instead of some smart math use a simple if/else to
round up or down. This helps people like me to understand
what the function does.

Signed-off-by: Harry Wentland 
---
 include/drm/drm_fixed.h | 15 ++-
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/include/drm/drm_fixed.h b/include/drm/drm_fixed.h
index cb842ba80ddd..8ee549f68537 100644
--- a/include/drm/drm_fixed.h
+++ b/include/drm/drm_fixed.h
@@ -77,6 +77,8 @@ static inline u32 dfixed_div(fixed20_12 A, fixed20_12 B)
 #define DRM_FIXED_DIGITS_MASK  (~DRM_FIXED_DECIMAL_MASK)
 #define DRM_FIXED_EPSILON  1LL
 #define DRM_FIXED_ALMOST_ONE   (DRM_FIXED_ONE - DRM_FIXED_EPSILON)
+#define DRM_FIXED_FRACTIONAL   0xll
+#define DRM_FIXED_HALF 0x8000ll
 
 /**
  * @drm_sm2fixp
@@ -106,11 +108,6 @@ static inline int drm_fixp2int(s64 a)
return ((s64)a) >> DRM_FIXED_POINT;
 }
 
-static inline int drm_fixp2int_round(s64 a)
-{
-   return drm_fixp2int(a + (1 << (DRM_FIXED_POINT_HALF - 1)));
-}
-
 static inline int drm_fixp2int_ceil(s64 a)
 {
if (a >= 0)
@@ -119,6 +116,14 @@ static inline int drm_fixp2int_ceil(s64 a)
return drm_fixp2int(a - DRM_FIXED_ALMOST_ONE);
 }
 
+static inline int drm_fixp2int_round(s64 a)
+{
+   if ((a & DRM_FIXED_FRACTIONAL) < DRM_FIXED_HALF)
+   return drm_fixp2int(a);
+   else
+   return drm_fixp2int_ceil(a);
+}
+
 static inline unsigned drm_fixp_msbset(s64 a)
 {
unsigned shift, sign = (a >> 63) & 1;
-- 
2.44.0



[RFC PATCH v4 00/42] Color Pipeline API w/ VKMS

2024-02-26 Thread Harry Wentland
This is an RFC set for a color pipeline API, along with a sample
implementation in VKMS. All the key API bits are here. VKMS now
supports two named transfer function colorops and two matrix
colorops. We have IGT tests that check all four of these colorops
with a pixel-by-pixel comparison that checks that these colorops
do what we expect them to do with a +/- 1 8 bpc code point margin.

The big new change with v4 is the addition of an amdgpu color
pipeline, for all AMD GPUs with DCN 3 and newer. Amdgpu now support
the following:

1. 1D Curve EOTF
2. 3x4 CTM
3. Multiplier
4. 1D Curve Inverse EOTF
5. 1D LUT
6. 1D Curve EOTF
7. 1D LUT

The supported curves for the 1D Curve type are:
- sRGB EOTF and its inverse
- PQ EOTF, scaled to [0.0, 125.0] and its inverse
- BT.2020/BT.709 OETF and its inverse

Note that the 1st and 5th colorops take the EOTF or Inverse
OETF while the 3rd colorop takes the Inverse EOTF or OETF.

We are working on two more ops for amdgpu, the HDR multiplier
and the 3DLUT, which will give us this:

1. 1D Curve EOTF
2. 3x4 CTM
3. HDR Multiplier
4. 1D Curve Inverse EOTF
5. 1D LUT
6. 3D LUT
7. 1D Curve EOTF
8. 1D LUT

This, essentially mirrors the color pipeline used by gamescope
and presented by Melissa Wen, with the exception of the DEGAM
LUT, which is not currently used. See
[1] 
https://indico.freedesktop.org/event/4/contributions/186/attachments/138/218/xdc2023-TheRainbowTreasureMap-MelissaWen.pdf

After this we'd like to also add the following ops:
- Scaler (Informational only)
- Color Encoding, to replace drm_plane's COLOR_ENCODING
- Color Range, to replace drm_plane's COLOR_RANGE

This patchset is grouped as follows:
 - Patches 1-3: couple general patches/fixes
 - Patches 4-7: introduce kunit to VKMS
 - Patch 7: description of motivation and details behind the
Color Pipeline API. If you're reading nothing else
but are interested in the topic I highly recommend
you take a look at this.
 - Patches 7-27: DRM core and VKMS changes for color pipeline API
 - Patches 28-40: DRM core and amdgpu changes for color pipeline API

VKMS patches could still be improved in a few ways, though the
payoff might be limited and I would rather focus on other work
at the moment. The most obvious thing to improve would be to
eliminate the hard-coded LUTs for identity, and sRGB, and replace
them with fixed-point math instead.

There are plenty of things that I would like to see here but
haven't had a chance to look at. These will (hopefully) be
addressed in future iterations, either in VKMS or amdgpu:
 - Clear documentation for each drm_colorop_type
 - Add custom LUT colorops to VKMS
 - Add pre-blending 3DLUT
 - How to support HW which can't bypass entire pipeline?
 - Add ability to create colorops that don't have BYPASS
 - Can we do a LOAD / COMMIT model for LUTs (and other properties)?
 - read-only scaling colorop which defines scaling taps and position
 - read-only color format colorop to define supported color formats
   for a pipeline
 - named matrices, for things like converting YUV to RGB

IGT tests can be found at
https://gitlab.freedesktop.org/hwentland/igt-gpu-tools/-/merge_requests/1

IGT patches are also being sent to the igt-dev mailing list.

If you prefer a gitlab MR for review you can find it at
https://gitlab.freedesktop.org/hwentland/linux/-/merge_requests/5

v4:
 - Add amdgpu color pipeline (WIP)
 - Don't block setting of deprecated properties, instead pass client cap
   to atomic check so drivers can ignore these props
 - Drop IOCTL definitions (Pekka)
 - Use enum property for colorop TYPE (Pekka)
 - A few cleanups to the docs (Pekka)
 - Rework the TYPE enum to name relation to avoid code duplication (Pekka)
 - Add missing function declarations (Chaitanya Kumar Borah)
 - Allow setting of NEXT property to NULL in _set_ function (Chaitanya Kumar 
Borah)
 - Add helper for creation of pipeline drm_plane property (Pekka)
 - Always create Bypass pipeline (Pekka)
 - A bunch of changes to VKMS kunit tests (Pekka)
 - Fix index in CTM doc (Pekka)

v3:
 - Abandon IOCTLs and discover colorops as clients iterate the pipeline
 - Remove need for libdrm
 - Add color_pipeline client cap and make mutually exclusive with
   COLOR_RANGE and COLOR_ENCODING properties
 - add CTM colorop to VKMS
 - Use include way for kunit testing static functions (Arthur)
 - Make TYPE a range property
 - Move enum drm_colorop_type to uapi header
 - and a bunch of smaller bits that are highlighted in the relevant commit
   description

v2:
 - Rebased on drm-misc-next
 - Introduce a VKMS Kunit so we can test LUT functionality in vkms_composer
 - Incorporate feedback in color_pipeline.rst doc
 - Add support for sRGB inverse EOTF
 - Add 2nd enumerated TF colorop to VKMS
 - Fix LUTs and some issues with applying LUTs in VKMS

Cc: Ville Syrjala 
Cc: Pekka Paalanen 
Cc: Simon Ser 
Cc: Harry Wentland 
Cc: Melissa Wen 
Cc: Jonas Ådahl 
Cc: Sebastian Wick 
Cc: Shashank Sharma 
Cc: Alexander Goins 
Cc: 

[PATCH] drm/vkms: Add information on how to benchmark

2024-02-26 Thread Arthur Grillo
Now that we have a defined benchmark for testing the driver, add
documentation on how to run it.

Signed-off-by: Arthur Grillo 
---
 Documentation/gpu/vkms.rst | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
index ba04ac7c2167..6d07f79f77ff 100644
--- a/Documentation/gpu/vkms.rst
+++ b/Documentation/gpu/vkms.rst
@@ -89,6 +89,12 @@ You can also run subtests if you do not want to run the 
entire test::
   sudo ./build/tests/kms_flip --run-subtest basic-plain-flip --device 
"sys:/sys/devices/platform/vkms"
   sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./build/tests/kms_flip 
--run-subtest basic-plain-flip
 
+If you are developing features that may affect performance, you can run the 
kms_fb_stress
+benchmark::
+
+  sudo ./build/benchmarks/kms_fb_stress --device 
"sys:/sys/devices/platform/vkms"
+  sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" 
./build/benchmarks/kms_fb_stress
+
 TODO
 
 

---
base-commit: eeb8e8d9f124f279e80ae679f4ba6e822ce4f95f
change-id: 20240226-bench-vkms-5b8b7aab255e

Best regards,
-- 
Arthur Grillo 



Re: [PATCH 1/2] drm/ttm: improve idle/busy handling v4

2024-02-26 Thread Thomas Hellström
Hi, Christian

On Fri, 2024-02-23 at 15:30 +0100, Christian König wrote:
> Am 06.02.24 um 13:56 schrieb Christian König:
> > Am 06.02.24 um 13:53 schrieb Thomas Hellström:
> > > Hi, Christian,
> > > 
> > > On Fri, 2024-01-26 at 15:09 +0100, Christian König wrote:
> > > > Previously we would never try to move a BO into the preferred
> > > > placements
> > > > when it ever landed in a busy placement since those were
> > > > considered
> > > > compatible.
> > > > 
> > > > Rework the whole handling and finally unify the idle and busy
> > > > handling.
> > > > ttm_bo_validate() is now responsible to try idle placement
> > > > first and
> > > > then
> > > > use the busy placement if that didn't worked.
> > > > 
> > > > Drawback is that we now always try the idle placement first for
> > > > each
> > > > validation which might cause some additional CPU overhead on
> > > > overcommit.
> > > > 
> > > > v2: fix kerneldoc warning and coding style
> > > > v3: take care of XE as well
> > > > v4: keep the ttm_bo_mem_space functionality as it is for now,
> > > > only
> > > > add
> > > >  new handling for ttm_bo_validate as suggested by Thomas
> > > > 
> > > > Signed-off-by: Christian König 
> > > > Reviewed-by: Zack Rusin  v3
> > > Sending this through xe CI, will try to review asap.
> > 
> > Take your time. At the moment people are bombarding me with work
> > and I 
> > have only two hands and one head as well :(
> 
> So I've digged myself out of that hole and would rather like to get
> this 
> new feature into 6.9.
> 
> Any time to review it? I can also plan some time to review your LRU 
> changes next week.
> 
> Thanks,
> Christian.

Sorry for the late response. Was planning to review but saw that there
was still an xe CI failure.

https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-129579v1/bat-atsm-2/igt@xe_evict_...@evict-overcommit-parallel-nofree-samefd.html

I haven't really had time to look into what might be causing this,
though.

/Thomas

> 
> > 
> > Christian.
> > 
> > > 
> > > /Thomas
> > > 
> > > 
> > > > ---
> > > >   drivers/gpu/drm/ttm/ttm_bo.c   | 231 +---
> > > > ---
> > > > -- 
> > > >   drivers/gpu/drm/ttm/ttm_resource.c |  16 +-
> > > >   include/drm/ttm/ttm_resource.h |   3 +-
> > > >   3 files changed, 121 insertions(+), 129 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/ttm/ttm_bo.c
> > > > b/drivers/gpu/drm/ttm/ttm_bo.c
> > > > index ba3f09e2d7e6..b12f435542a9 100644
> > > > --- a/drivers/gpu/drm/ttm/ttm_bo.c
> > > > +++ b/drivers/gpu/drm/ttm/ttm_bo.c
> > > > @@ -724,64 +724,36 @@ static int ttm_bo_add_move_fence(struct
> > > > ttm_buffer_object *bo,
> > > >   return ret;
> > > >   }
> > > >   -/*
> > > > - * Repeatedly evict memory from the LRU for @mem_type until we
> > > > create enough
> > > > - * space, or we've evicted everything and there isn't enough
> > > > space.
> > > > - */
> > > > -static int ttm_bo_mem_force_space(struct ttm_buffer_object
> > > > *bo,
> > > > -      const struct ttm_place *place,
> > > > -      struct ttm_resource **mem,
> > > > -      struct ttm_operation_ctx *ctx)
> > > > -{
> > > > -    struct ttm_device *bdev = bo->bdev;
> > > > -    struct ttm_resource_manager *man;
> > > > -    struct ww_acquire_ctx *ticket;
> > > > -    int ret;
> > > > -
> > > > -    man = ttm_manager_type(bdev, place->mem_type);
> > > > -    ticket = dma_resv_locking_ctx(bo->base.resv);
> > > > -    do {
> > > > -    ret = ttm_resource_alloc(bo, place, mem);
> > > > -    if (likely(!ret))
> > > > -    break;
> > > > -    if (unlikely(ret != -ENOSPC))
> > > > -    return ret;
> > > > -    ret = ttm_mem_evict_first(bdev, man, place, ctx,
> > > > -      ticket);
> > > > -    if (unlikely(ret != 0))
> > > > -    return ret;
> > > > -    } while (1);
> > > > -
> > > > -    return ttm_bo_add_move_fence(bo, man, *mem, ctx-
> > > > > no_wait_gpu);
> > > > -}
> > > > -
> > > >   /**
> > > > - * ttm_bo_mem_space
> > > > + * ttm_bo_alloc_resource - Allocate backing store for a BO
> > > >    *
> > > > - * @bo: Pointer to a struct ttm_buffer_object. the data of
> > > > which
> > > > - * we want to allocate space for.
> > > > - * @placement: Proposed new placement for the buffer object.
> > > > - * @mem: A struct ttm_resource.
> > > > + * @bo: Pointer to a struct ttm_buffer_object of which we want
> > > > a
> > > > resource for
> > > > + * @placement: Proposed new placement for the buffer object
> > > >    * @ctx: if and how to sleep, lock buffers and alloc memory
> > > > + * @force_space: If we should evict buffers to force space
> > > > + * @res: The resulting struct ttm_resource.
> > > >    *
> > > > - * Allocate memory space for the buffer object pointed to by
> > > > @bo,
> > > > using
> > > > - * the placement flags in @placement, potentially evicting
> > > > other
> > > > idle buffer objects.
> > > > - * This function may sleep while waiting for space to 

Re: [PATCH v2 0/6] Pinephone video out fixes (flipping between two frames)

2024-02-26 Thread Erico Nunes
Hello,

On Mon, Feb 26, 2024 at 6:29 PM Jernej Škrabec  wrote:
>
> Dne ponedeljek, 26. februar 2024 ob 08:13:42 CET je Frank Oltmanns napisal(a):
> > It seems to me that all options for changing the GPU's rate in a stable
> > manner have been exhausted. There seems to be no common interpretation
> > what the phrase "Clock output of PLL_GPU can be used for GPU;and dynamic
> > frequency scaling is not supported" in the Allwinner A64 manual (chapter
> > 3.3.3) means.
> >
> > The BSP uses a fixed rate of 432 MHz. Unless one of you has a clever
> > idea, I suggest to remove the OPPs from the device tree and set the GPU
> > to 432 MHz.
> >
> > What are your thoughts on that?
>
> I can't find original source of these points. So I'm good with removing
> them. But instead of fully removing table, you can just leave one point and
> it should work.

I had posted in
https://gitlab.freedesktop.org/mesa/mesa/-/issues/8410#note_2216628
that I also noticed the A64 datasheet specifically claims that except
for PLL_CPUX and PLL_DDR1, other PLLs don't support frequency scaling.
I was never able to find any evidence that it is actually supposed to
work anyway (perhaps it was hope?). Since you also looked in the BSP
and there is still no evidence that it is supported, I support that we
should likely just remove the OPPs.

Also, I wanted to point out that my series
https://patchwork.freedesktop.org/series/128856/#rev2 was merged to
lima recently. That was the root cause of the "flipping between two
frames" issue that people most probably hit. I highly recommend that
people using the Pinephone update their kernel to include those fixes
to fix that issue. As you mentioned about that symptom here, I just
wanted to point out that it wouldn't be possible to fix the "flipping
frames" issue with just fixes to A64 clock, it does need lima driver
fixes.

Thanks

Erico


[linux-next:master] BUILD REGRESSION 8552c902efe7ef670b6961fb8885b67961aeb629

2024-02-26 Thread kernel test robot
tree/branch: 
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
branch HEAD: 8552c902efe7ef670b6961fb8885b67961aeb629  Add linux-next specific 
files for 20240226

Error/Warning reports:

https://lore.kernel.org/oe-kbuild-all/202402261912.yaxzeprg-...@intel.com

Error/Warning: (recently discovered and may have been fixed)

drivers/gpu/drm/xe/xe_ggtt.c:78:9: error: implicit declaration of function 
'writeq'; did you mean 'writeb'? [-Werror=implicit-function-declaration]
fs/ubifs/journal.c:369: warning: expecting prototype for wake_up_reservation(). 
Prototype was for add_or_start_queue() instead
make[2]: *** kselftest/livepatch/test_modules: No such file or directory.  Stop.

Unverified Error/Warning (likely false positive, please contact us if 
interested):

{standard input}:1344: Warning: overflow in branch to .L91; converted into 
longer instruction sequence

Error/Warning ids grouped by kconfigs:

gcc_recent_errors
|-- arc-allmodconfig
|   `-- 
drivers-gpu-drm-xe-xe_ggtt.c:error:implicit-declaration-of-function-writeq
|-- arm-multi_v7_defconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- arm-tegra_defconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- arm64-randconfig-001-20240226
|   `-- fs-ntfs3-frecord.c:warning:unused-variable-i_size
|-- arm64-randconfig-002-20240226
|   `-- fs-ntfs3-frecord.c:warning:unused-variable-i_size
|-- arm64-randconfig-003-20240226
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- csky-allmodconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- csky-allyesconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- csky-randconfig-002-20240226
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- csky-randconfig-r052-20240226
|   `-- fs-ntfs3-frecord.c:warning:unused-variable-i_size
|-- i386-allyesconfig
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- i386-randconfig-052-20240226
|   `-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|-- i386-randconfig-053-20240226
|   |-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|   `-- fs-ntfs3-frecord.c:warning:unused-variable-i_size
|-- i386-randconfig-054-20240226
|   |-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|   `-- fs-ntfs3-frecord.c:warning:unused-variable-i_size
|-- i386-randconfig-061-20240226
|   |-- 
drivers-video-backlight-ktd2801-backlight.c:sparse:sparse:symbol-ktd2801_timing-was-not-declared.-Should-it-be-static
|   `-- io_uring-io_uring.c:sparse:sparse:cast-to-restricted-io_req_flags_t
|-- i386-randconfig-141-20240226
|   |-- 
drivers-usb-typec-tcpm-tcpm.c-tcpm_pd_svdm()-error:uninitialized-symbol-modep_prime-.
|   |-- 
drivers-usb-typec-ucsi-ucsi_acpi.c-ucsi_dell_sync_write()-warn:missing-error-code-ret
|   `-- 
mm-page_owner.c-stack_print()-warn:unsigned-nr_entries-is-never-less-than-zero.
|-- loongarch-defconfig
|   `-- 
fs-ubifs-journal.c:warning:expecting-prototype-for-wake_up_reservation().-Prototype-was-for-add_or_start_queue()-instead
|-- loongarch-randconfig-001-20240226
|   |-- 
drivers-gpu-drm-nouveau-nvkm-subdev-gsp-r535.c:warning:Function-parameter-or-struct-member-gsp-not-described-in-nvkm_gsp_radix3_sg
|   `-- fs-ntfs3-frecord.c:warning:unused-variable-i_size
|-- m68k-randconfig-r051-20240226
|   `-- fs-ntfs3-frecord.c:warning:unused-variable-i_size
|-- m68k-randconfig-r061-20240226
|   `-- fs-ntfs3-frecord.c:warning:unused-variable-i_size
|-- m68k-randconfig-r111-20240226
|   |-- 
drivers-video-backlight-ktd2801-backlight.c:sparse:sparse:symbol-ktd2801_timing-was-not-declared.-Should-it-be-static
|   |-- fs-ntfs3-frecord.c:warning:unused-variable-i_size
|   |-- fs-ntfs3-fslog.c:sparse:sparse:restricted-__le32-degrades-to-integer
|   |-- io_uring-io_uring.c:sparse:sparse:cast-to-restricted-io_req_flags_t
|   |-- 
sound-core-sound_kunit.c:sparse:sparse:incorrect-type-in-argument-(different-base-types)-expected-restricted-snd_pcm_format_t-usertype-format-got-int
|   `-- 
sound-core-sound_kunit.c:sparse:sparse:restricted-snd_pcm_format_t-degrades-to-integer
|-- m68k-randconfig-r121-20240226
|   |-- fs-ntfs3-fslog.c:sparse:sparse:restricted-__le32-degrades-to-integer

Re: [PATCH 2/2] fbcon: Defer console takeover for splash screens to first switch

2024-02-26 Thread Hans de Goede
Hi All,

On 2/2/24 09:53, Daniel van Vugt wrote:
> Until now, deferred console takeover only meant defer until there is
> output. But that risks stepping on the toes of userspace splash screens,
> as console messages may appear before the splash screen. So check for the
> "splash" parameter (as used by Plymouth) and if present then extend the
> deferral until the first switch.

Daniel, thank you for your patch but I do not believe that this
is the right solution. Deferring fbcon takeover further then
after the first text is output means that any errors about e.g.
a corrupt initrd or the kernel erroring out / crashing will not
be visible.

When the kernel e.g. oopses or panics because of not finding
its rootfs (I tested the latter option when writing the original
deferred fbcon takeover code) then fbcon must takeover and
print the messages from the dying kernel so that the user has
some notion of what is going wrong.

And since your patch seems to delay switching till the first
vc-switch this means that e.g. even after say gdm refusing
to start because of issues there still will be no text
output. This makes debugging various issues much harder.

Moreover Fedora has been doing flickerfree boot for many
years without needing this.

The kernel itself will be quiet as long as you set
CONFIG_CONSOLE_LOGLEVEL_QUIET=3 Ubuntu atm has set this
to 4 which means any kernel pr_err() or dev_err()
messages will get through and since there are quite
a few false positives of those Ubuntu really needs
to set CONFIG_CONSOLE_LOGLEVEL_QUIET=3 to fix part of:
https://bugs.launchpad.net/bugs/1970069

After that it is "just" a matter of not making userspace
output anything unless it has errors to report.

systemd already is quiet by default (only logging
errors) when quiet is on the kernel commandline.

So any remaining issues are Ubuntu specific boot
process bits and Ubuntu really should be able to
make those by silent unless they have important
info (errors or other unexpected things) to report.

Given that this will make debugging boot issues
much harder and that there are other IMHO better
alternatives I'm nacking this patch: NACK.

FWIW I believe that I'm actually saving Ubuntu
from shooting themselves in the foot here,
hiding all sort of boot errors (like the initrd
not finding /) until the user does a magic
alt+f2 followed by alt+f1 incantation really is
not doing yourself any favors wrt debugging any
sort of boot failures.

Regards,

Hans





> Closes: https://bugs.launchpad.net/bugs/1970069
> Cc: Mario Limonciello 
> Signed-off-by: Daniel van Vugt 
> ---
>  drivers/video/fbdev/core/fbcon.c | 32 +---
>  1 file changed, 29 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/video/fbdev/core/fbcon.c 
> b/drivers/video/fbdev/core/fbcon.c
> index 63af6ab034..5b9f7635f7 100644
> --- a/drivers/video/fbdev/core/fbcon.c
> +++ b/drivers/video/fbdev/core/fbcon.c
> @@ -76,6 +76,7 @@
>  #include  /* For counting font checksums */
>  #include 
>  #include 
> +#include 
>  
>  #include "fbcon.h"
>  #include "fb_internal.h"
> @@ -146,6 +147,7 @@ static inline void fbcon_map_override(void)
>  
>  #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER
>  static bool deferred_takeover = true;
> +static int initial_console = -1;
>  #else
>  #define deferred_takeover false
>  #endif
> @@ -3341,7 +3343,7 @@ static void fbcon_register_existing_fbs(struct 
> work_struct *work)
>   console_unlock();
>  }
>  
> -static struct notifier_block fbcon_output_nb;
> +static struct notifier_block fbcon_output_nb, fbcon_switch_nb;
>  static DECLARE_WORK(fbcon_deferred_takeover_work, 
> fbcon_register_existing_fbs);
>  
>  static int fbcon_output_notifier(struct notifier_block *nb,
> @@ -3358,6 +3360,21 @@ static int fbcon_output_notifier(struct notifier_block 
> *nb,
>  
>   return NOTIFY_OK;
>  }
> +
> +static int fbcon_switch_notifier(struct notifier_block *nb,
> +  unsigned long action, void *data)
> +{
> + struct vc_data *vc = data;
> +
> + WARN_CONSOLE_UNLOCKED();
> +
> + if (vc->vc_num != initial_console) {
> + dummycon_unregister_switch_notifier(_switch_nb);
> + dummycon_register_output_notifier(_output_nb);
> + }
> +
> + return NOTIFY_OK;
> +}
>  #endif
>  
>  static void fbcon_start(void)
> @@ -3370,7 +3387,14 @@ static void fbcon_start(void)
>  
>   if (deferred_takeover) {
>   fbcon_output_nb.notifier_call = fbcon_output_notifier;
> - dummycon_register_output_notifier(_output_nb);
> + fbcon_switch_nb.notifier_call = fbcon_switch_notifier;
> + initial_console = fg_console;
> +
> + if (cmdline_find_option_bool(boot_command_line, "splash"))
> + dummycon_register_switch_notifier(_switch_nb);
> + else
> + dummycon_register_output_notifier(_output_nb);
> +
>   return;
>   }
>  #endif
> @@ -3417,8 +3441,10 @@ 

[PATCH] drm/msm/a6xx: Improve error handling in a6xx_gmu_rpmh_init()

2024-02-26 Thread Markus Elfring
From: Markus Elfring 
Date: Mon, 26 Feb 2024 18:46:38 +0100

The label “err” was used as a target for two statements despite of
the implementation detail that failure conditions could be handled better.

* Thus return directly after a call of the function “a6xx_gmu_get_mmio”
  failed at the beginning.

* Reorder affected statements at the end.

* Adjust a jump target.

* Omit an extra pointer check which became unnecessary
  with this refactoring.

Signed-off-by: Markus Elfring 
---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 8c4900444b2c..55a34f11eb9a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -525,7 +525,7 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
bool pdc_in_aop = false;

if (IS_ERR(pdcptr))
-   goto err;
+   return;

if (adreno_is_a650(adreno_gpu) ||
adreno_is_a660_family(adreno_gpu) ||
@@ -541,7 +541,7 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
if (!pdc_in_aop) {
seqptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc_seq");
if (IS_ERR(seqptr))
-   goto err;
+   goto unmap_io_pdc;
}

/* Disable SDE clock gating */
@@ -634,11 +634,11 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)

a6xx_rpmh_stop(gmu);

-err:
-   if (!IS_ERR_OR_NULL(pdcptr))
-   iounmap(pdcptr);
if (!IS_ERR_OR_NULL(seqptr))
iounmap(seqptr);
+
+unmap_io_pdc:
+   iounmap(pdcptr);
 }

 /*
--
2.43.2



Re: [PATCH 1/3] drm/amdgpu: Refuse to create a KMS FB for non-P2P exported dma-bufs

2024-02-26 Thread Michel Dänzer
On 2024-02-26 17:53, Christian König wrote:
> Am 26.02.24 um 17:50 schrieb Michel Dänzer:
>> On 2024-02-26 17:46, Michel Dänzer wrote:
>>> On 2024-02-26 17:34, Christian König wrote:
>>>
 My question is why has it worked so far? I mean we are not doing this 
 since yesterday and the problem only shows up now?
>>> Yes, Wayland compositors are only starting to try and make use of this now.
>> To expand on this, mutter will want to do something like this as well sooner 
>> or later. I suspect it's the same for others like kwin, sway etc.
> 
> Yeah, but we have done similar things with X decades before. E.g. basically 
> the client sends a BO to the server for displaying it.

The scenario in https://gitlab.freedesktop.org/mesa/mesa/-/issues/10635 is 
direct scanout of a client buffer on a secondary dGPU, while the compositor 
uses the APU as the primary compositing GPU.

AFAIR Xorg has never supported direct scanout of client buffers in this 
scenario. Secondary GPU scanout is always done from a separate local buffer 
allocated by Xorg / the driver.

This is Wayland compositors pushing the envelope.


> Why we suddenly have to juggle with the fact that it is DMA-buf shared with 
> another device?

The problematic case is if the Wayland compositor has to produce a composited 
frame (e.g. due to a notification or other window popping up over the 
fullscreen window), but the client hasn't attached a new buffer to the 
fullscreen surface, so the compositor has to use the contents of the same 
client buffer which is still being scanned out by the dGPU for compositing with 
the APU.


-- 
Earthling Michel Dänzer|  https://redhat.com
Libre software enthusiast  | Mesa and Xwayland developer



Re: [PATCH] net: ethernet: ti: am65-cpsw: Add minimal XDP support

2024-02-26 Thread Julien Panis

Hello Simon,

Thank you for the review.

On 2/26/24 18:25, Simon Horman wrote:

On Fri, Feb 23, 2024 at 12:01:37PM +0100, Julien Panis wrote:

This patch adds XDP (eXpress Data Path) support to TI AM65 CPSW
Ethernet driver. The following features are implemented:
- NETDEV_XDP_ACT_BASIC (XDP_PASS, XDP_TX, XDP_DROP, XDP_ABORTED)
- NETDEV_XDP_ACT_REDIRECT (XDP_REDIRECT)
- NETDEV_XDP_ACT_NDO_XMIT (ndo_xdp_xmit callback)

Signed-off-by: Julien Panis 

...


@@ -440,6 +476,27 @@ static void am65_cpsw_nuss_tx_cleanup(void *data, 
dma_addr_t desc_dma)
dev_kfree_skb_any(skb);
  }
  
+static struct sk_buff *am65_cpsw_alloc_skb(struct net_device *ndev, unsigned int len)

+{
+   struct page *page;
+   struct sk_buff *skb;

nit: please arrange local variables in reverse xmas tree order,
  from longest line to shortest in new code.

  This tool can be useful: https://github.com/ecree-solarflare/xmastree


You mean, for the new functions introduced in this patch only ?




+
+   page = dev_alloc_pages(0);

nit: Maybe dev_alloc_page() is appropriate here?


Absolutely.




+   if (unlikely(!page))
+   return NULL;
+
+   len += AM65_CPSW_HEADROOM;
+
+   skb = build_skb(page_address(page), len);
+   if (unlikely(!skb))

Does page need to be freed here?


Of course it does ! This will be fixed in the next version.




+   return NULL;
+
+   skb_reserve(skb, AM65_CPSW_HEADROOM + NET_IP_ALIGN);
+   skb->dev = ndev;
+
+   return skb;
+}

...




Re: [PATCH v2 9/9] ARM: dts: chameleonv3: Add video device nodes

2024-02-26 Thread Krzysztof Kozlowski
On 26/02/2024 13:27, Paweł Anikiel wrote:
> On Mon, Feb 26, 2024 at 1:07 PM Krzysztof Kozlowski
>  wrote:
>>
>> On 26/02/2024 12:09, Paweł Anikiel wrote:
>>> On Mon, Feb 26, 2024 at 10:15 AM Krzysztof Kozlowski
>>>  wrote:

 On 21/02/2024 17:02, Paweł Anikiel wrote:
> Add device nodes for the video system present on the Chameleon v3.
> It consists of six framebuffers and two Intel Displayport receivers.
>
> Signed-off-by: Paweł Anikiel 
> ---

 ...

> + dprx_sst: dp-receiver@c0064000 {
> + compatible = "intel,dprx-20.0.1";
> + reg = <0xc0064000 0x800>;
> + interrupt-parent = <_sst_irq>;
> + interrupts = <0 IRQ_TYPE_EDGE_RISING>;
> + intel,max-link-rate = <0x1e>;

 Rate is not in hex! Rate is in Hz, at least usually...

 Fix your bindings...
>>>
>>> This is the DisplayPort link rate, for which the allowed values are
>>> 8.1 Gbps, 5.4 Gbps, 2.7 Gbps, or 1.62 Gbps. The standard way to encode
>>> them (used in the DisplayPort DPCD registers and this device's
>>
>> Then it is in bps or some other units:
>>
>> https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/property-units.yaml
>>
>>> configuration) is by multiples of 0.27Gbps. This value (AFAIK) is
>>> usually represented in hex, so 8.1Gbps would be 0x1e.
>>
>> No, the value is represented in logical units. Frequency in Hz. Rate in
>> bps/kbps/etc. Voltage in volts.
> 
> Okay, thanks for the info. So if I understand correctly, the max link
> rate should be represented in bps in the devicetree, and then be

or kbps

> converted to the per 0.27Gbps value by the driver?

If driver needs some register-based value, then yes.

> 
> One problem is that the values here are too large to be represented in
> bps (since the datatype is uint32). Can the property be in Mbps
> instead?

Can be. You can submit a patch to dtschema (patch to DT spec list or
github pull request) adding '-mbps' as well.

Best regards,
Krzysztof



Re: [PATCH v2 0/6] Pinephone video out fixes (flipping between two frames)

2024-02-26 Thread Jernej Škrabec
Dne ponedeljek, 26. februar 2024 ob 08:13:42 CET je Frank Oltmanns napisal(a):
> Hi Jernej,
> hi Maxime,
> hi Ondřej,
> 
> On 2024-02-19 at 10:41:19 +0100, Frank Oltmanns  wrote:
> > Hi Ondřej,
> >
> > On 2024-02-11 at 20:25:29 +0100, Ondřej Jirman  wrote:
> >> Hi Frank,
> >>
> >> On Sun, Feb 11, 2024 at 04:09:16PM +0100, Frank Oltmanns wrote:
> >>> Hi Ondřej,
> >>>
> >>> On 2024-02-05 at 17:02:00 +0100, Ondřej Jirman  wrote:
> >>> > On Mon, Feb 05, 2024 at 04:54:07PM +0100, Ondřej Jirman wrote:
> >>> >> On Mon, Feb 05, 2024 at 04:22:23PM +0100, Frank Oltmanns wrote:
> >>> >>
> >>> >> [...]
> >>> >>
> >>> >> Also sunxi-ng clk driver does apply NM factors at once to PLL_GPU 
> >>> >> clock,
> >>> >> which can cause sudden frequency increase beyond intended output 
> >>> >> frequency,
> >>> >> because division is applied immediately while multiplication is 
> >>> >> reflected
> >>> >> slowly.
> >>> >>
> >>> >> Eg. if you're changing divider from 7 to 1, you can get a sudden 7x 
> >>> >> output
> >>> >> frequency spike, before PLL VCO manages to lower the frequency through 
> >>> >> N clk
> >>> >> divider feedback loop and lock on again. This can mess up whatever's 
> >>> >> connected
> >>> >> to the output quite badly.
> >>> >>
> >>> >> You'd have to put logging on kernel writes to PLL_GPU register to see 
> >>> >> what
> >>> >> is written in there and if divider is lowered significantly on some GPU
> >>> >> devfreq frequency transitions.
> >>>
> >>> By looking at the clocks in clk_summary in debugfs, the rate of PLL-GPU
> >>> always matches the rate of the GPU (at least at 120, 312, and 432 MHz).
> >>> This is further underlined by the fact, that none of the rates can be
> >>> achieved by integer dividing one of the other rates. sunxi-ng would
> >>> only favor a different rate for pll-gpu than the one that is requested
> >>> for the gpu, if pll-gpu is already running at a rate such that there
> >>> exists an M ∈ {1, 2, 3, 4, 5, 6, 7, 8}, where
> >>>   rate of pll-gpu / M = requested gpu rate
> >>> or if the requested rate could not be reached directly by pll-gpu. Both
> >>> is not the case for the rates in question (120, 192, 312, and 432 MHz).
> >>>
> >>> This means that the following divisor/multipliers are used by sunxi-ng's
> >>> ccu_nm:
> >>> N =  5, M = 1 for 120 MHz (min value without PATCH 6)
> >>> N =  8, M = 1 for 192 MHz (min value after applying PATCH 6)
> >>> N = 13, M = 1 for 312 MHz
> >>> N = 18, M = 1 for 432 MHz
> >>>
> >>> So, with or without PATCH 6, the divider stays constant and it's only
> >>> the multiplier that changes. This means, there should be no unexpected
> >>> frequency spikes, right?
> >>
> >> Maybe. Thanks for giving it a try. There may still be other kinds of 
> >> glitches
> >> even if the divisor stays the same. It all depends how the register update 
> >> is
> >> implemented in the PLL block. It's hard to say. I guess, unless Allwinner
> >> guarantees glitchless output from a given PLL when changing its parameters,
> >> you can't rely on the output being clean during changes.
> >>
> >>> >> It's also unclear what happens when FRAC_CLK_OUT or PLL_MODE_SEL 
> >>> >> changes.
> >>>
> >>> Those are not changed once the clock is initialized. The bug however
> >>> occurs hours or days after booting. IMO, this makes it unlikely that this
> >>> could be the culprit.
> >>>
> >>> >> Maybe not much because M is supposed to be set to 1, but you still 
> >>> >> need to
> >>> >> care when enabling fractional mode, and setting M to 1 because that's 
> >>> >> exactly
> >>> >> the bad scenario if M was previously higher than 1.
> >>> >>
> >>> >> It's tricky.
> >>> >>
> >>> >> Having GPU module clock gated during PLL config changes may help! You 
> >>> >> can
> >>> >> do that without locking yourself out, unlike with the CPU PLL.
> >>> >>
> >>> >> There's a gate enable bit for it at GPU_CLK_REG.SCLK_GATING. (page 122)
> >>>
> >>> The GPU should already be properly gated:
> >>> https://elixir.bootlin.com/linux/v6.7.4/source/drivers/clk/sunxi-ng/ccu-sun50i-a64.c#L599
> >>
> >> How so? That's just clock declaration. How does it guarantee the clock to 
> >> the
> >> module is gated during parent PLL configuration changes?
> >>
> >
> > You're of course right.
> >
> > I now tried using a similar approach like the one for changes for on
> > PLL-CPU. It's using a notifier to connect the CPU to the 24 MHz
> > oscillator and, after PLL-CPU is at its new rate, connecting it back to
> > PLL-CPU.
> >
> > For the GPU my approach was to disable the GPU prior to changing
> > PLL-GPU's rate and then re-enabling it, once the rate change is
> > complete. I think, that's what you were proposing, right?
> >
> > Unfortunately, this results in a frozen phone even more quickly.
> >
> > Below is my code. Again, it doesn't solve the problem, but maybe
> > somebody can spot what I'm doing wrong.
> 
> It seems to me that all options for changing the GPU's rate in a stable
> manner have been exhausted. There seems to 

Re: [PATCH v2 8/9] media: dt-bindings: Add Intel Displayport RX IP

2024-02-26 Thread Krzysztof Kozlowski
On 26/02/2024 13:43, Paweł Anikiel wrote:
> +  intel,max-stream-count:
> +$ref: /schemas/types.yaml#/definitions/uint32
> +description: Max stream count configuration parameter
> +
> +  port:
> +$ref: /schemas/graph.yaml#/properties/port
> +description: SST main link

 I don't understand why you have both port and ports. Shouldn't this be
 under ports?
>>>
>>> I put both so that you can use the shorter port property when the
>>> device only has one port (i.e. no MST support). It would work fine
>>> without it. If you think that's unnecessary, I can remove it (and use
>>> the ports property even if there is only one).
>>
>> No, it is fine, but then you need allOf: which will restrict to only one
>> of them: either port or ports.
> 
> There already is an allOf below that says that ports is required for
> MST support and port is required otherwise. Isn't this enough?

Add both port and ports and see if it is enough.

Best regards,
Krzysztof



  1   2   3   4   >