From: Harry Wentland <harry.wentland@xxxxxxx> We want to make sure userspace is aware of the 1D LUT interpolation. While linear interpolation is common it might not be supported on all HW. Give driver implementers a way to specify their interpolation. Signed-off-by: Alex Hung <alex.hung@xxxxxxx> Signed-off-by: Harry Wentland <harry.wentland@xxxxxxx> --- v7: - Fix a checkpatch long-line warning - Modify state->size to colorop->lut_size .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 6 ++-- drivers/gpu/drm/drm_atomic.c | 2 ++ drivers/gpu/drm/drm_colorop.c | 36 ++++++++++++++++++- include/drm/drm_colorop.h | 19 +++++++++- include/uapi/drm/drm_mode.h | 13 +++++++ 5 files changed, 72 insertions(+), 4 deletions(-) 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 d0777691862b..92c9f3fb0254 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 @@ -131,7 +131,8 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr goto cleanup; } - ret = drm_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES); + ret = drm_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES, + DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR); if (ret) goto cleanup; @@ -163,7 +164,8 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr goto cleanup; } - ret = drm_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES); + ret = drm_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES, + DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR); if (ret) goto cleanup; diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 1fa6818794d6..9a17fe11bcb3 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -795,6 +795,8 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p, break; case DRM_COLOROP_1D_LUT: drm_printf(p, "\tsize=%d\n", colorop->lut_size); + drm_printf(p, "\tinterpolation=%s\n", + drm_get_colorop_lut1d_interpolation_name(colorop->lut1d_interpolation)); drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0); break; case DRM_COLOROP_CTM_3X4: diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c index 9fbfb2b89b1b..e8d8806e94cf 100644 --- a/drivers/gpu/drm/drm_colorop.c +++ b/drivers/gpu/drm/drm_colorop.c @@ -78,6 +78,9 @@ static const char * const colorop_curve_1d_type_names[] = { [DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF] = "PQ 125 Inverse EOTF", }; +static const struct drm_prop_enum_list drm_colorop_lut1d_interpolation_list[] = { + { DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR, "Linear" }, +}; /* Init Helpers */ @@ -234,10 +237,12 @@ static int drm_colorop_create_data_prop(struct drm_device *dev, struct drm_color * @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 * @return zero on success, -E value on failure */ 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_plane *plane, uint32_t lut_size, + enum drm_colorop_lut1d_interpolation_type lut1d_interpolation) { struct drm_property *prop; int ret; @@ -257,6 +262,17 @@ int drm_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *co drm_object_attach_property(&colorop->base, colorop->lut_size_property, lut_size); colorop->lut_size = lut_size; + /* Interpolation */ + prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, "LUT1D_INTERPOLATION", + drm_colorop_lut1d_interpolation_list, + ARRAY_SIZE(drm_colorop_lut1d_interpolation_list)); + if (!prop) + return -ENOMEM; + + colorop->lut1d_interpolation_property = prop; + drm_object_attach_property(&colorop->base, prop, lut1d_interpolation); + colorop->lut1d_interpolation = lut1d_interpolation; + /* data */ ret = drm_colorop_create_data_prop(dev, colorop); if (ret) @@ -411,6 +427,9 @@ static const char * const colorop_type_name[] = { [DRM_COLOROP_CTM_3X4] = "3x4 Matrix", [DRM_COLOROP_MULTIPLIER] = "Multiplier", }; +static const char * const colorop_lut1d_interpolation_name[] = { + [DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR] = "Linear", +}; const char *drm_get_colorop_type_name(enum drm_colorop_type type) { @@ -428,6 +447,21 @@ const char *drm_get_colorop_curve_1d_type_name(enum drm_colorop_curve_1d_type ty return colorop_curve_1d_type_names[type]; } +/** + * drm_get_colorop_lut1d_interpolation_name: return a string for interpolation type + * @type: interpolation 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_lut1d_interpolation_name(enum drm_colorop_lut1d_interpolation_type type) +{ + if (WARN_ON(type >= ARRAY_SIZE(colorop_lut1d_interpolation_name))) + return "unknown"; + + return colorop_lut1d_interpolation_name[type]; +} + /** * drm_colorop_set_next_property - sets the next pointer * @colorop: drm colorop diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h index d84f457a2b65..01c7f5cd6019 100644 --- a/include/drm/drm_colorop.h +++ b/include/drm/drm_colorop.h @@ -253,6 +253,21 @@ struct drm_colorop { */ uint32_t lut_size; + /** + * @lut1d_interpolation: + * + * Read-only + * Interpolation for DRM_COLOROP_1D_LUT + */ + enum drm_colorop_lut1d_interpolation_type lut1d_interpolation; + + /** + * @lut1d_interpolation_property: + * + * Read-only property for DRM_COLOROP_1D_LUT interpolation + */ + struct drm_property *lut1d_interpolation_property; + /** * @curve_1d_type_property: * @@ -322,7 +337,8 @@ static inline struct drm_colorop *drm_colorop_find(struct drm_device *dev, int drm_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop, struct drm_plane *plane, u64 supported_tfs); 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_plane *plane, uint32_t lut_size, + enum drm_colorop_lut1d_interpolation_type lut1d_interpolation); int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop, struct drm_plane *plane); int drm_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop, @@ -376,6 +392,7 @@ const char *drm_get_colorop_type_name(enum drm_colorop_type type); * const pointer and hence is threadsafe. */ const char *drm_get_colorop_curve_1d_type_name(enum drm_colorop_curve_1d_type type); +const char *drm_get_colorop_lut1d_interpolation_name(enum drm_colorop_lut1d_interpolation_type type); void drm_colorop_set_next_property(struct drm_colorop *colorop, struct drm_colorop *next); diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 96cb32e6980c..5ef87cb5b242 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -915,6 +915,19 @@ enum drm_colorop_type { DRM_COLOROP_MULTIPLIER, }; +/** + * enum drm_colorop_lut1d_interpolation_type - type of interpolation for 1D LUTs + */ +enum drm_colorop_lut1d_interpolation_type { + /** + * @DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR: + * + * Linear interpolation. Values between points of the LUT will be + * linearly interpolated. + */ + DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR, +}; + /** * struct drm_plane_size_hint - Plane size hints * @width: The width of the plane in pixel -- 2.43.0