Introduce the core object and state for the fast-loading (DMA) 3D LUT
colorop. Add drm_plane_colorop_3dlut_dma_init(), which creates the
read-only LUT_3D_FORMATS blob (advertising the driver's accepted struct
drm_mode_3dlut_mode entries), the LUT_3D_FORMAT selection range, and the
FB_ID object property. The colorop must allow bypass, since removing
the LUT framebuffer bypasses it.

The colorop state gains a selected-format index and a reference-counted
framebuffer pointer; the state duplicate/destroy helpers take and drop
the framebuffer reference so an in-flight LUT buffer stays pinned for the
lifetime of the state.

Signed-off-by: Harry Wentland <[email protected]>
---
 drivers/gpu/drm/drm_colorop.c | 86 +++++++++++++++++++++++++++++++++++
 include/drm/drm_colorop.h     | 56 +++++++++++++++++++++++
 2 files changed, 142 insertions(+)

diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index b30413ad797b..3fc7884befbf 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -28,6 +28,7 @@
 #include <drm/drm_print.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_plane.h>
+#include <drm/drm_framebuffer.h>
 
 #include "drm_crtc_internal.h"
 
@@ -464,6 +465,87 @@ int drm_plane_colorop_3dlut_init(struct drm_device *dev, 
struct drm_colorop *col
 }
 EXPORT_SYMBOL(drm_plane_colorop_3dlut_init);
 
+/**
+ * drm_plane_colorop_3dlut_dma_init - Initialize a DRM_COLOROP_3D_LUT_DMA
+ *
+ * @dev: DRM device
+ * @colorop: The drm_colorop object to initialize
+ * @plane: The associated drm_plane
+ * @funcs: control functions for the new colorop
+ * @formats: array of accepted buffer formats advertised to userspace
+ * @num_formats: number of entries in @formats
+ * @flags: bitmask of misc, see DRM_COLOROP_FLAG_* defines. Must include
+ *         DRM_COLOROP_FLAG_ALLOW_BYPASS, since removing the LUT framebuffer
+ *         bypasses the colorop.
+ *
+ * Initializes a fast-loading (DMA) 3D LUT colorop. The colorop advertises
+ * the accepted buffer formats via a read-only LUT_3D_FORMATS blob, lets
+ * userspace select one via LUT_3D_FORMAT, and points FB_ID at the
+ * framebuffer holding the LUT data.
+ *
+ * @return zero on success, -E value on failure
+ */
+int drm_plane_colorop_3dlut_dma_init(struct drm_device *dev, struct 
drm_colorop *colorop,
+                                    struct drm_plane *plane,
+                                    const struct drm_colorop_funcs *funcs,
+                                    const struct drm_mode_3dlut_mode *formats,
+                                    size_t num_formats, uint32_t flags)
+{
+       struct drm_property_blob *blob;
+       struct drm_property *prop;
+       int ret;
+
+       if (!formats || !num_formats)
+               return -EINVAL;
+
+       /* Removing the LUT framebuffer bypasses the colorop. */
+       if (drm_WARN_ON(dev, !(flags & DRM_COLOROP_FLAG_ALLOW_BYPASS)))
+               return -EINVAL;
+
+       ret = drm_plane_colorop_init(dev, colorop, plane, funcs,
+                                    DRM_COLOROP_3D_LUT_DMA, flags);
+       if (ret)
+               return ret;
+
+       /* LUT_3D_FORMATS: immutable blob listing the accepted buffer formats */
+       blob = drm_property_create_blob(dev,
+                                       num_formats * sizeof(*formats),
+                                       formats);
+       if (IS_ERR(blob))
+               return PTR_ERR(blob);
+
+       prop = drm_property_create(dev, DRM_MODE_PROP_IMMUTABLE | 
DRM_MODE_PROP_BLOB,
+                                  "LUT_3D_FORMATS", 0);
+       if (!prop) {
+               drm_property_blob_put(blob);
+               return -ENOMEM;
+       }
+       colorop->lut_3d_formats_property = prop;
+       colorop->lut_3d_formats_blob = blob;
+       drm_object_attach_property(&colorop->base, prop, blob->base.id);
+
+       /* LUT_3D_FORMAT: selected index into the LUT_3D_FORMATS array */
+       prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, 
"LUT_3D_FORMAT",
+                                        0, num_formats - 1);
+       if (!prop)
+               return -ENOMEM;
+       colorop->lut_3d_format_property = prop;
+       drm_object_attach_property(&colorop->base, prop, 0);
+
+       /* FB_ID: framebuffer holding the LUT data */
+       prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC, "FB_ID",
+                                         DRM_MODE_OBJECT_FB);
+       if (!prop)
+               return -ENOMEM;
+       colorop->fb_property = prop;
+       drm_object_attach_property(&colorop->base, prop, 0);
+
+       drm_colorop_reset(colorop);
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_plane_colorop_3dlut_dma_init);
+
 /**
  * drm_plane_colorop_fixed_matrix_init - Initialize a DRM_COLOROP_FIXED_MATRIX
  *
@@ -545,6 +627,8 @@ static void 
__drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colo
 
        if (state->data)
                drm_property_blob_get(state->data);
+       if (state->fb)
+               drm_framebuffer_get(state->fb);
 }
 
 struct drm_colorop_state *
@@ -573,6 +657,8 @@ drm_atomic_helper_colorop_duplicate_state(struct 
drm_colorop *colorop)
 static void __drm_atomic_helper_colorop_destroy_state(struct drm_colorop_state 
*state)
 {
        drm_property_blob_put(state->data);
+       if (state->fb)
+               drm_framebuffer_put(state->fb);
 }
 
 void drm_colorop_atomic_destroy_state(struct drm_colorop *colorop,
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index 26ef67c835e2..95922eb1044c 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -31,6 +31,8 @@
 #include <drm/drm_mode.h>
 #include <drm/drm_property.h>
 
+struct drm_framebuffer;
+
 /* DRM colorop flags */
 #define DRM_COLOROP_FLAG_ALLOW_BYPASS  (1<<0)  /* Allow bypass on the 
drm_colorop */
 
@@ -312,6 +314,22 @@ struct drm_colorop_state {
         */
        enum drm_colorop_fixed_matrix_type fixed_matrix_type;
 
+       /**
+        * @lut_3d_format:
+        *
+        * Index into the LUT_3D_FORMATS blob selecting the buffer format for
+        * a DRM_COLOROP_3D_LUT_DMA colorop.
+        */
+       uint32_t lut_3d_format;
+
+       /**
+        * @fb:
+        *
+        * Reference-counted framebuffer holding the LUT data for a
+        * DRM_COLOROP_3D_LUT_DMA colorop.
+        */
+       struct drm_framebuffer *fb;
+
        /** @state: backpointer to global drm_atomic_commit */
        struct drm_atomic_commit *state;
 };
@@ -488,6 +506,39 @@ struct drm_colorop {
         */
        struct drm_property *fixed_matrix_type_property;
 
+       /**
+        * @lut_3d_formats_property:
+        *
+        * Immutable blob property listing the accepted buffer formats (an
+        * array of struct drm_mode_3dlut_mode) for a DRM_COLOROP_3D_LUT_DMA
+        * colorop.
+        */
+       struct drm_property *lut_3d_formats_property;
+
+       /**
+        * @lut_3d_format_property:
+        *
+        * Range property selecting an entry, by index, of the
+        * @lut_3d_formats_blob array.
+        */
+       struct drm_property *lut_3d_format_property;
+
+       /**
+        * @fb_property:
+        *
+        * Object property (DRM_MODE_OBJECT_FB) pointing at the framebuffer
+        * that holds the LUT data for a DRM_COLOROP_3D_LUT_DMA colorop.
+        */
+       struct drm_property *fb_property;
+
+       /**
+        * @lut_3d_formats_blob:
+        *
+        * The advertised list backing @lut_3d_formats_property, retained for
+        * validation during atomic check.
+        */
+       struct drm_property_blob *lut_3d_formats_blob;
+
        /**
         * @next_property:
         *
@@ -544,6 +595,11 @@ int drm_plane_colorop_3dlut_init(struct drm_device *dev, 
struct drm_colorop *col
                                 uint32_t lut_size,
                                 enum drm_colorop_lut3d_interpolation_type 
interpolation,
                                 uint32_t flags);
+int drm_plane_colorop_3dlut_dma_init(struct drm_device *dev, struct 
drm_colorop *colorop,
+                                    struct drm_plane *plane,
+                                    const struct drm_colorop_funcs *funcs,
+                                    const struct drm_mode_3dlut_mode *formats,
+                                    size_t num_formats, uint32_t flags);
 int drm_plane_colorop_fixed_matrix_init(struct drm_device *dev, struct 
drm_colorop *colorop,
                                        struct drm_plane *plane,
                                        const struct drm_colorop_funcs *funcs,
-- 
2.56.0

Reply via email to