Introduce support for a post-blend color pipeline API analogous to the pre-blend color pipeline API. While the pre-blend color pipeline was configured through a COLOR_PIPELINE property attached to a drm_plane, the post-blend color pipeline is configured through a COLOR_PIPELINE property on the drm_crtc.
Since colorops can now be attached to either a drm_plane or a drm_crtc, rework the helpers to account for both cases. Also introduce a new cap, DRM_CLIENT_CAP_POST_BLEND_COLOR_PIPELINE, to enable support for post-blend color pipelines, and prevent the now legacy GAMMA_LUT, DEGAMMA_LUT, GAMMA_LUT_SIZE and CTM properties from being exposed. Signed-off-by: Nícolas F. R. A. Prado <nfrapr...@collabora.com> --- drivers/gpu/drm/drm_atomic.c | 32 ++++++-- drivers/gpu/drm/drm_atomic_uapi.c | 50 ++++++++++++- drivers/gpu/drm/drm_colorop.c | 144 +++++++++++++++++++++++++++++------- drivers/gpu/drm/drm_connector.c | 1 + drivers/gpu/drm/drm_crtc.c | 77 +++++++++++++++++++ drivers/gpu/drm/drm_crtc_internal.h | 6 ++ drivers/gpu/drm/drm_ioctl.c | 7 ++ drivers/gpu/drm/drm_mode_object.c | 20 +++++ drivers/gpu/drm/drm_plane.c | 36 ++------- include/drm/drm_atomic.h | 20 +++++ include/drm/drm_atomic_uapi.h | 2 + include/drm/drm_colorop.h | 16 +++- include/drm/drm_crtc.h | 19 +++++ include/drm/drm_file.h | 7 ++ include/uapi/drm/drm.h | 16 ++++ 15 files changed, 383 insertions(+), 70 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 3ab32fe7fe1cbf9057c3763d979638dce013d82b..558d389d59d9a44d3cd1048ed365848f62b4d62d 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -472,6 +472,8 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p, drm_printf(p, "\tplane_mask=%x\n", state->plane_mask); drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask); drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask); + drm_printf(p, "\tcolor-pipeline=%d\n", + state->color_pipeline ? state->color_pipeline->base.id : 0); drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode)); if (crtc->funcs->atomic_print_state) @@ -617,9 +619,15 @@ drm_atomic_get_colorop_state(struct drm_atomic_state *state, if (colorop_state) return colorop_state; - ret = drm_modeset_lock(&colorop->plane->mutex, state->acquire_ctx); - if (ret) - return ERR_PTR(ret); + if (colorop->plane) { + ret = drm_modeset_lock(&colorop->plane->mutex, state->acquire_ctx); + if (ret) + return ERR_PTR(ret); + } else { + ret = drm_modeset_lock(&colorop->crtc->mutex, state->acquire_ctx); + if (ret) + return ERR_PTR(ret); + } colorop_state = drm_atomic_helper_colorop_duplicate_state(colorop); if (!colorop_state) @@ -2003,11 +2011,21 @@ static void __drm_state_dump(struct drm_device *dev, struct drm_printer *p, return; list_for_each_entry(colorop, &config->colorop_list, head) { - if (take_locks) - drm_modeset_lock(&colorop->plane->mutex, NULL); + if (take_locks) { + if (colorop->plane) + drm_modeset_lock(&colorop->plane->mutex, NULL); + else + drm_modeset_lock(&colorop->crtc->mutex, NULL); + + } drm_atomic_colorop_print_state(p, colorop->state); - if (take_locks) - drm_modeset_unlock(&colorop->plane->mutex); + if (take_locks) { + if (colorop->plane) + drm_modeset_unlock(&colorop->plane->mutex); + else + drm_modeset_unlock(&colorop->crtc->mutex); + + } } list_for_each_entry(plane, &config->plane_list, head) { diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index b7cc6945864274bedd21dd5b73494f9aae216888..a826758cf0b6205e2ba49734070bc83ffb7c08df 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -287,6 +287,33 @@ drm_atomic_set_colorop_for_plane(struct drm_plane_state *plane_state, } EXPORT_SYMBOL(drm_atomic_set_colorop_for_plane); +/** + * drm_atomic_set_colorop_for_crtc - set colorop for crtc + * @crtc_state: atomic state object for the crtc + * @colorop: colorop to use for the crtc + * + * Helper function to select the color pipeline on a crtc by setting + * it to the first drm_colorop element of the pipeline. + */ +void +drm_atomic_set_colorop_for_crtc(struct drm_crtc_state *crtc_state, + struct drm_colorop *colorop) +{ + struct drm_crtc *crtc = crtc_state->crtc; + + if (colorop) + drm_dbg_atomic(crtc->dev, + "Set [COLOROP:%d] for [CRTC:%d:%s] state %p\n", + colorop->base.id, crtc->base.id, crtc->name, + crtc_state); + else + drm_dbg_atomic(crtc->dev, + "Set [NOCOLOROP] for [CRTC:%d:%s] state %p\n", + crtc->base.id, crtc->name, crtc_state); + + crtc_state->color_pipeline = colorop; +} +EXPORT_SYMBOL(drm_atomic_set_colorop_for_crtc); /** * drm_atomic_set_crtc_for_connector - set CRTC for connector @@ -396,8 +423,8 @@ static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state, } static int drm_atomic_crtc_set_property(struct drm_crtc *crtc, - struct drm_crtc_state *state, struct drm_property *property, - uint64_t val) + struct drm_crtc_state *state, struct drm_file *file_priv, + struct drm_property *property, uint64_t val) { struct drm_device *dev = crtc->dev; struct drm_mode_config *config = &dev->mode_config; @@ -406,7 +433,17 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc, if (property == config->prop_active) state->active = val; - else if (property == config->prop_mode_id) { + else if (property == crtc->color_pipeline_property) { + /* find DRM colorop object */ + struct drm_colorop *colorop = NULL; + + colorop = drm_colorop_find(dev, file_priv, val); + + if (val && !colorop) + return -EACCES; + + drm_atomic_set_colorop_for_crtc(state, colorop); + } else if (property == config->prop_mode_id) { struct drm_property_blob *mode = drm_property_lookup_blob(dev, val); ret = drm_atomic_set_mode_prop_for_crtc(state, mode); @@ -487,6 +524,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc, *val = 0; else if (property == crtc->scaling_filter_property) *val = state->scaling_filter; + else if (property == crtc->color_pipeline_property) + *val = (state->color_pipeline) ? state->color_pipeline->base.id : 0; else if (crtc->funcs->atomic_get_property) return crtc->funcs->atomic_get_property(crtc, state, property, val); else { @@ -1047,6 +1086,8 @@ int drm_atomic_get_property(struct drm_mode_object *obj, if (colorop->plane) WARN_ON(!drm_modeset_is_locked(&colorop->plane->mutex)); + else + WARN_ON(!drm_modeset_is_locked(&colorop->crtc->mutex)); ret = drm_atomic_colorop_get_property(colorop, colorop->state, property, val); @@ -1204,7 +1245,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state, } ret = drm_atomic_crtc_set_property(crtc, - crtc_state, prop, prop_value); + crtc_state, file_priv, prop, prop_value); break; } case DRM_MODE_OBJECT_PLANE: { @@ -1604,6 +1645,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, state->acquire_ctx = &ctx; state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET); state->plane_color_pipeline = file_priv->plane_color_pipeline; + state->post_blend_color_pipeline = file_priv->post_blend_color_pipeline; retry: copied_objs = 0; diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c index a1b36cd488f0a014425a9192ffe5fcc4d2c1afaa..d53de1438d23def74a77730cacd3651131e82cbe 100644 --- a/drivers/gpu/drm/drm_colorop.c +++ b/drivers/gpu/drm/drm_colorop.c @@ -90,8 +90,9 @@ static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] = /* Init Helpers */ -static int drm_plane_colorop_init(struct drm_device *dev, struct drm_colorop *colorop, - struct drm_plane *plane, enum drm_colorop_type type, uint32_t flags) +static int drm_common_colorop_init(struct drm_device *dev, + struct drm_colorop *colorop, + enum drm_colorop_type type, uint32_t flags) { struct drm_mode_config *config = &dev->mode_config; struct drm_property *prop; @@ -104,7 +105,6 @@ static int drm_plane_colorop_init(struct drm_device *dev, struct drm_colorop *co colorop->base.properties = &colorop->properties; colorop->dev = dev; colorop->type = type; - colorop->plane = plane; colorop->next = NULL; list_add_tail(&colorop->head, &config->colorop_list); @@ -153,6 +153,34 @@ static int drm_plane_colorop_init(struct drm_device *dev, struct drm_colorop *co return ret; } +static int drm_crtc_colorop_init(struct drm_device *dev, + struct drm_colorop *colorop, + struct drm_crtc *crtc, + enum drm_colorop_type type, uint32_t flags) +{ + int ret; + + ret = drm_common_colorop_init(dev, colorop, type, flags); + + colorop->crtc = crtc; + + return ret; +} + +static int drm_plane_colorop_init(struct drm_device *dev, + struct drm_colorop *colorop, + struct drm_plane *plane, + enum drm_colorop_type type, uint32_t flags) +{ + int ret; + + ret = drm_common_colorop_init(dev, colorop, type, flags); + + colorop->plane = plane; + + return ret; +} + /** * drm_colorop_cleanup - Cleanup a drm_colorop object in color_pipeline * @@ -279,29 +307,16 @@ static int drm_colorop_create_data_prop(struct drm_device *dev, struct drm_color return 0; } -/** - * drm_plane_colorop_curve_1d_lut_init - Initialize a DRM_COLOROP_1D_LUT - * - * @dev: DRM device - * @colorop: The drm_colorop object to initialize - * @plane: The associated drm_plane - * @lut_size: LUT size supported by driver - * @lut1d_interpolation: 1D LUT interpolation type - * @flags: bitmask of misc, see DRM_COLOROP_FLAG_* defines. - * @return zero on success, -E value on failure - */ -int drm_plane_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *colorop, - struct drm_plane *plane, uint32_t lut_size, - enum drm_colorop_lut1d_interpolation_type lut1d_interpolation, - uint32_t flags) +static int +drm_common_colorop_curve_1d_lut_init(struct drm_device *dev, + struct drm_colorop *colorop, + uint32_t lut_size, + enum drm_colorop_lut1d_interpolation_type lut1d_interpolation, + uint32_t flags) { struct drm_property *prop; int ret; - ret = drm_plane_colorop_init(dev, colorop, plane, DRM_COLOROP_1D_LUT, flags); - if (ret) - return ret; - /* initialize 1D LUT only attribute */ /* LUT size */ prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_ATOMIC, @@ -333,17 +348,69 @@ int drm_plane_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_color return 0; } -EXPORT_SYMBOL(drm_plane_colorop_curve_1d_lut_init); -int drm_plane_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop, - struct drm_plane *plane, uint32_t flags) +/** + * drm_crtc_colorop_curve_1d_lut_init - Initialize a DRM_COLOROP_1D_LUT + * + * @dev: DRM device + * @colorop: The drm_colorop object to initialize + * @crtc: The associated drm_crtc + * @lut_size: LUT size supported by driver + * @lut1d_interpolation: 1D LUT interpolation type + * @flags: bitmask of misc, see DRM_COLOROP_FLAG_* defines. + * @return zero on success, -E value on failure + */ +int +drm_crtc_colorop_curve_1d_lut_init(struct drm_device *dev, + struct drm_colorop *colorop, + struct drm_crtc *crtc, uint32_t lut_size, + enum drm_colorop_lut1d_interpolation_type lut1d_interpolation, + uint32_t flags) { int ret; - ret = drm_plane_colorop_init(dev, colorop, plane, DRM_COLOROP_CTM_3X4, flags); + ret = drm_crtc_colorop_init(dev, colorop, crtc, DRM_COLOROP_1D_LUT, flags); if (ret) return ret; + return drm_common_colorop_curve_1d_lut_init(dev, colorop, lut_size, + lut1d_interpolation, flags); +} +EXPORT_SYMBOL(drm_crtc_colorop_curve_1d_lut_init); + +/** + * drm_plane_colorop_curve_1d_lut_init - Initialize a DRM_COLOROP_1D_LUT + * + * @dev: DRM device + * @colorop: The drm_colorop object to initialize + * @plane: The associated drm_plane + * @lut_size: LUT size supported by driver + * @lut1d_interpolation: 1D LUT interpolation type + * @flags: bitmask of misc, see DRM_COLOROP_FLAG_* defines. + * @return zero on success, -E value on failure + */ +int +drm_plane_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *colorop, + struct drm_plane *plane, uint32_t lut_size, + enum drm_colorop_lut1d_interpolation_type lut1d_interpolation, + uint32_t flags) +{ + int ret; + + ret = drm_plane_colorop_init(dev, colorop, plane, DRM_COLOROP_1D_LUT, flags); + if (ret) + return ret; + + return drm_common_colorop_curve_1d_lut_init(dev, colorop, lut_size, + lut1d_interpolation, flags); +} +EXPORT_SYMBOL(drm_plane_colorop_curve_1d_lut_init); + +static int drm_common_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop, + uint32_t flags) +{ + int ret; + ret = drm_colorop_create_data_prop(dev, colorop); if (ret) return ret; @@ -352,6 +419,31 @@ int drm_plane_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *c return 0; } + +int drm_crtc_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop, + struct drm_crtc *crtc, uint32_t flags) +{ + int ret; + + ret = drm_crtc_colorop_init(dev, colorop, crtc, DRM_COLOROP_CTM_3X4, flags); + if (ret) + return ret; + + return drm_common_colorop_ctm_3x4_init(dev, colorop, flags); +} +EXPORT_SYMBOL(drm_crtc_colorop_ctm_3x4_init); + +int drm_plane_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop, + struct drm_plane *plane, uint32_t flags) +{ + int ret; + + ret = drm_plane_colorop_init(dev, colorop, plane, DRM_COLOROP_CTM_3X4, flags); + if (ret) + return ret; + + return drm_common_colorop_ctm_3x4_init(dev, colorop, flags); +} EXPORT_SYMBOL(drm_plane_colorop_ctm_3x4_init); /** diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 4d6dc9ebfdb5bc730b1aff7a184448af7b93f078..f58cfd2131139ff3e613adc4dbb9ddbedf724dc7 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -3440,6 +3440,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, */ ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic, file_priv->plane_color_pipeline, + file_priv->post_blend_color_pipeline, (uint32_t __user *)(unsigned long)(out_resp->props_ptr), (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr), &out_resp->count_props); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 46655339003db2a1b43441434839e26f61d79b4e..94238163ff1254c721df39c030bc99a31d3bb92a 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -959,3 +959,80 @@ bool drm_crtc_in_clone_mode(struct drm_crtc_state *crtc_state) return hweight32(crtc_state->encoder_mask) > 1; } EXPORT_SYMBOL(drm_crtc_in_clone_mode); + +struct drm_property * +drm_common_create_color_pipeline_property(struct drm_device *dev, struct drm_mode_object *obj, + const struct drm_prop_enum_list *pipelines, + int num_pipelines) +{ + struct drm_prop_enum_list *all_pipelines; + struct drm_property *prop; + int len = 0; + int i; + + all_pipelines = kcalloc(num_pipelines + 1, + sizeof(*all_pipelines), + GFP_KERNEL); + + if (!all_pipelines) { + drm_err(dev, "failed to allocate color pipeline\n"); + return ERR_PTR(-ENOMEM); + } + + /* Create default Bypass color pipeline */ + all_pipelines[len].type = 0; + all_pipelines[len].name = "Bypass"; + len++; + + /* Add all other color pipelines */ + for (i = 0; i < num_pipelines; i++, len++) { + all_pipelines[len].type = pipelines[i].type; + all_pipelines[len].name = pipelines[i].name; + } + + prop = drm_property_create_enum(dev, DRM_MODE_PROP_ATOMIC, + "COLOR_PIPELINE", + all_pipelines, len); + if (IS_ERR(prop)) { + kfree(all_pipelines); + return prop; + } + + drm_object_attach_property(obj, prop, 0); + + kfree(all_pipelines); + return prop; +} + +/** + * drm_crtc_create_color_pipeline_property - create a new color pipeline + * property + * + * @crtc: drm CRTC + * @pipelines: list of pipelines + * @num_pipelines: number of pipelines + * + * Create the COLOR_PIPELINE CRTC property to specify color pipelines on + * the CRTC. + * + * RETURNS: + * Zero for success or -errno + */ +int drm_crtc_create_color_pipeline_property(struct drm_crtc *crtc, + const struct drm_prop_enum_list *pipelines, + int num_pipelines) +{ + struct drm_property *prop; + + prop = drm_common_create_color_pipeline_property(crtc->dev, + &crtc->base, + pipelines, + num_pipelines); + if (IS_ERR(prop)) + return PTR_ERR(prop); + + crtc->color_pipeline_property = prop; + + return 0; +} +EXPORT_SYMBOL(drm_crtc_create_color_pipeline_property); diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index c094092296448093c5cd192ecdc8ea9a50769c90..c53f154e5392a10c326c844b7321666275f9ac02 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -35,6 +35,7 @@ #ifndef __DRM_CRTC_INTERNAL_H__ #define __DRM_CRTC_INTERNAL_H__ +#include <drm/drm_property.h> #include <linux/err.h> #include <linux/types.h> @@ -79,6 +80,10 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc, int drm_crtc_register_all(struct drm_device *dev); void drm_crtc_unregister_all(struct drm_device *dev); int drm_crtc_force_disable(struct drm_crtc *crtc); +struct drm_property * +drm_common_create_color_pipeline_property(struct drm_device *dev, struct drm_mode_object *obj, + const struct drm_prop_enum_list *pipelines, + int num_pipelines); struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc); @@ -164,6 +169,7 @@ void drm_mode_object_unregister(struct drm_device *dev, struct drm_mode_object *object); int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic, bool plane_color_pipeline, + bool post_blend_color_pipeline, uint32_t __user *prop_ptr, uint64_t __user *prop_values, uint32_t *arg_count_props); diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index ff193155129e7e863888d8958458978566b144f8..2c81f63fee428ca85f3c626d892ea6097b964e88 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -380,6 +380,13 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) return -EINVAL; file_priv->plane_color_pipeline = req->value; break; + case DRM_CLIENT_CAP_POST_BLEND_COLOR_PIPELINE: + if (!file_priv->atomic) + return -EINVAL; + if (req->value > 1) + return -EINVAL; + file_priv->post_blend_color_pipeline = req->value; + break; default: return -EINVAL; } diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c index b45d501b10c868c6d9b7a5a8760eadbd7b372a6a..c9e20d12e8fd311f71b9d6bc8d575624751d33ad 100644 --- a/drivers/gpu/drm/drm_mode_object.c +++ b/drivers/gpu/drm/drm_mode_object.c @@ -388,6 +388,7 @@ EXPORT_SYMBOL(drm_object_property_get_default_value); /* helper for getconnector and getproperties ioctls */ int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic, bool plane_color_pipeline, + bool post_blend_color_pipeline, uint32_t __user *prop_ptr, uint64_t __user *prop_values, uint32_t *arg_count_props) @@ -416,6 +417,24 @@ int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic, continue; } + if (post_blend_color_pipeline && obj->type == DRM_MODE_OBJECT_CRTC) { + struct drm_crtc *crtc = obj_to_crtc(obj); + struct drm_mode_config mode_config = crtc->dev->mode_config; + + if (prop == mode_config.gamma_lut_property || + prop == mode_config.degamma_lut_property || + prop == mode_config.gamma_lut_size_property || + prop == mode_config.ctm_property) + continue; + } + + if (!post_blend_color_pipeline && obj->type == DRM_MODE_OBJECT_CRTC) { + struct drm_crtc *crtc = obj_to_crtc(obj); + + if (prop == crtc->color_pipeline_property) + continue; + } + if (*arg_count_props > count) { ret = __drm_object_property_get_value(obj, prop, &val); if (ret) @@ -475,6 +494,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, ret = drm_mode_object_get_properties(obj, file_priv->atomic, file_priv->plane_color_pipeline, + file_priv->post_blend_color_pipeline, (uint32_t __user *)(unsigned long)(arg->props_ptr), (uint64_t __user *)(unsigned long)(arg->prop_values_ptr), &arg->count_props); diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index f6cfa8ac090c7bc49c7f276993bba7e9800da140..60dbfcab495600dd44c15260a1fa6135db59c6e2 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -1839,43 +1839,17 @@ int drm_plane_create_color_pipeline_property(struct drm_plane *plane, const struct drm_prop_enum_list *pipelines, int num_pipelines) { - struct drm_prop_enum_list *all_pipelines; struct drm_property *prop; - int len = 0; - int i; - - all_pipelines = kcalloc(num_pipelines + 1, - sizeof(*all_pipelines), - GFP_KERNEL); - - if (!all_pipelines) { - drm_err(plane->dev, "failed to allocate color pipeline\n"); - return -ENOMEM; - } - /* Create default Bypass color pipeline */ - all_pipelines[len].type = 0; - all_pipelines[len].name = "Bypass"; - len++; - - /* Add all other color pipelines */ - for (i = 0; i < num_pipelines; i++, len++) { - all_pipelines[len].type = pipelines[i].type; - all_pipelines[len].name = pipelines[i].name; - } - - prop = drm_property_create_enum(plane->dev, DRM_MODE_PROP_ATOMIC, - "COLOR_PIPELINE", - all_pipelines, len); - if (IS_ERR(prop)) { - kfree(all_pipelines); + prop = drm_common_create_color_pipeline_property(plane->dev, + &plane->base, + pipelines, + num_pipelines); + if (IS_ERR(prop)) return PTR_ERR(prop); - } - drm_object_attach_property(&plane->base, prop, 0); plane->color_pipeline_property = prop; - kfree(all_pipelines); return 0; } EXPORT_SYMBOL(drm_plane_create_color_pipeline_property); diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 678708df9cdb90b4266127193a92183069f18688..8c42c584aefbf0034b2163d90538e80099b0dadb 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -482,6 +482,26 @@ struct drm_atomic_state { */ bool plane_color_pipeline : 1; + /** + * @post_blend_color_pipeline: + * + * Indicates whether this atomic state originated with a client that + * set the DRM_CLIENT_CAP_POST_BLEND_COLOR_PIPELINE. + * + * Drivers and helper functions should use this to ignore legacy + * properties that are incompatible with the drm_crtc COLOR_PIPELINE + * behavior, such as: + * + * - GAMMA_LUT + * - DEGAMMA_LUT + * - GAMMA_LUT_SIZE + * - CTM + * + * or any other driver-specific properties that might affect pixel + * values. + */ + bool post_blend_color_pipeline : 1; + /** * @colorops: * diff --git a/include/drm/drm_atomic_uapi.h b/include/drm/drm_atomic_uapi.h index 4363155233267b93767c895fa6085544e2277442..4dc191f6f929d73deee9812025c48275a33cf770 100644 --- a/include/drm/drm_atomic_uapi.h +++ b/include/drm/drm_atomic_uapi.h @@ -52,6 +52,8 @@ void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, struct drm_framebuffer *fb); void drm_atomic_set_colorop_for_plane(struct drm_plane_state *plane_state, struct drm_colorop *colorop); +void drm_atomic_set_colorop_for_crtc(struct drm_crtc_state *crtc_state, + struct drm_colorop *colorop); int __must_check drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, struct drm_crtc *crtc); diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h index d61c6c40e47162cb8b1e7db58b6746c43ac5d202..710a6199ebc5498a3f664de39ea07dbc95944eb7 100644 --- a/include/drm/drm_colorop.h +++ b/include/drm/drm_colorop.h @@ -206,10 +206,16 @@ struct drm_colorop { /** * @plane: * - * The plane on which the colorop sits. A drm_colorop is always unique - * to a plane. + * The plane on which the colorop sits if it is a pre-blend colorop. + * In this case it is unique to the plane. + * + * @crtc: + * + * The CRTC on which the colorop sits if it is a post-blend colorop. + * In this case it is unique to the CRTC. */ struct drm_plane *plane; + struct drm_crtc *crtc; /** * @state: @@ -370,6 +376,10 @@ static inline struct drm_colorop *drm_colorop_find(struct drm_device *dev, void drm_colorop_pipeline_destroy(struct drm_device *dev); +int drm_crtc_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *colorop, + struct drm_crtc *crtc, uint32_t lut_size, + enum drm_colorop_lut1d_interpolation_type lut1d_interpolation, + uint32_t flags); int drm_plane_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop, struct drm_plane *plane, u64 supported_tfs, uint32_t flags); int drm_plane_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *colorop, @@ -378,6 +388,8 @@ int drm_plane_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_color uint32_t flags); int drm_plane_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop, struct drm_plane *plane, uint32_t flags); +int drm_crtc_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop, + struct drm_crtc *crtc, uint32_t flags); int drm_plane_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop, struct drm_plane *plane, uint32_t flags); int drm_plane_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *colorop, diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index caa56e039da2a748cf40ebf45b37158acda439d9..df03637ca25abd45e96b5944229297f776fd046d 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -274,6 +274,14 @@ struct drm_crtc_state { */ struct drm_property_blob *gamma_lut; + /** + * @color_pipeline: + * + * The first colorop of the active color pipeline, or NULL, if no + * color pipeline is active. + */ + struct drm_colorop *color_pipeline; + /** * @target_vblank: * @@ -1088,6 +1096,14 @@ struct drm_crtc { */ struct drm_property *scaling_filter_property; + /** + * @color_pipeline_property: + * + * Optional "COLOR_PIPELINE" enum property for specifying + * a color pipeline to use on the CRTC. + */ + struct drm_property *color_pipeline_property; + /** * @state: * @@ -1323,5 +1339,8 @@ static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev, int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc, unsigned int supported_filters); +int drm_crtc_create_color_pipeline_property(struct drm_crtc *crtc, + const struct drm_prop_enum_list *pipelines, + int num_pipelines); bool drm_crtc_in_clone_mode(struct drm_crtc_state *crtc_state); #endif /* __DRM_CRTC_H__ */ diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 1a3018e4a537b3341acb50187d47371f6b781b9d..42b9a43baa18079af8ec2ea5b1484b23c497beb0 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -213,6 +213,13 @@ struct drm_file { */ bool plane_color_pipeline; + /** + * @post_blend_color_pipeline: + * + * True if client understands post-blend color pipelines + */ + bool post_blend_color_pipeline; + /** * @was_master: * diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 27cc159c1d275c7a7fe057840ef792f30a582bb7..1191b142ebaa5478376308f169f9ce8591580d9d 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -921,6 +921,22 @@ struct drm_get_cap { */ #define DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE 7 +/** + * DRM_CLIENT_CAP_POST_BLEND_COLOR_PIPELINE + * + * If set to 1 the DRM core will allow setting the COLOR_PIPELINE + * property on a &drm_crtc, as well as drm_colorop properties. + * + * Setting of these crtc properties will be rejected when this client + * cap is set: + * - GAMMA_LUT + * - DEGAMMA_LUT + * - CTM + * + * The client must enable &DRM_CLIENT_CAP_ATOMIC first. + */ +#define DRM_CLIENT_CAP_POST_BLEND_COLOR_PIPELINE 8 + /* DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ struct drm_set_client_cap { __u64 capability; -- 2.47.2