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
