drm: automatic legacy gamma support

To support legacy gamma ioctls the drivers need to set
drm_crtc_funcs.gamma_set either to a custom implementation or to
drm_atomic_helper_legacy_gamma_set. Most of the atomic drivers do the
latter.

We can simplify this by making the core handle it automatically.

Move the drm_atomic_helper_legacy_gamma_set() functionality into
drm_color_mgmt.c to make drm_mode_gamma_set_ioctl() use
drm_crtc_funcs.gamma_set if set or GAMMA_LUT property if not.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Philippe Cornu <philippe.cornu@st.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20201211114237.213288-2-tomi.valkeinen@ti.com
This commit is contained in:
Tomi Valkeinen
2020-12-11 13:42:36 +02:00
parent 5c0e4110f7
commit 6ca2ab8086
19 changed files with 102 additions and 101 deletions

View File

@@ -5452,7 +5452,6 @@ static void dm_disable_vblank(struct drm_crtc *crtc)
static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
.reset = dm_crtc_reset_state, .reset = dm_crtc_reset_state,
.destroy = amdgpu_dm_crtc_destroy, .destroy = amdgpu_dm_crtc_destroy,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.set_config = drm_atomic_helper_set_config, .set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip, .page_flip = drm_atomic_helper_page_flip,
.atomic_duplicate_state = dm_crtc_duplicate_state, .atomic_duplicate_state = dm_crtc_duplicate_state,

View File

@@ -550,7 +550,6 @@ static void komeda_crtc_vblank_disable(struct drm_crtc *crtc)
} }
static const struct drm_crtc_funcs komeda_crtc_funcs = { static const struct drm_crtc_funcs komeda_crtc_funcs = {
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.destroy = drm_crtc_cleanup, .destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config, .set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip, .page_flip = drm_atomic_helper_page_flip,

View File

@@ -510,7 +510,6 @@ static void malidp_crtc_disable_vblank(struct drm_crtc *crtc)
} }
static const struct drm_crtc_funcs malidp_crtc_funcs = { static const struct drm_crtc_funcs malidp_crtc_funcs = {
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.destroy = drm_crtc_cleanup, .destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config, .set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip, .page_flip = drm_atomic_helper_page_flip,

View File

@@ -820,7 +820,6 @@ static const struct drm_crtc_funcs armada_crtc_funcs = {
.cursor_set = armada_drm_crtc_cursor_set, .cursor_set = armada_drm_crtc_cursor_set,
.cursor_move = armada_drm_crtc_cursor_move, .cursor_move = armada_drm_crtc_cursor_move,
.destroy = armada_drm_crtc_destroy, .destroy = armada_drm_crtc_destroy,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.set_config = drm_atomic_helper_set_config, .set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip, .page_flip = drm_atomic_helper_page_flip,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,

View File

@@ -903,7 +903,6 @@ static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc,
static const struct drm_crtc_funcs ast_crtc_funcs = { static const struct drm_crtc_funcs ast_crtc_funcs = {
.reset = ast_crtc_reset, .reset = ast_crtc_reset,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.destroy = drm_crtc_cleanup, .destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config, .set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip, .page_flip = drm_atomic_helper_page_flip,

View File

@@ -473,7 +473,6 @@ static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = {
.atomic_destroy_state = atmel_hlcdc_crtc_destroy_state, .atomic_destroy_state = atmel_hlcdc_crtc_destroy_state,
.enable_vblank = atmel_hlcdc_crtc_enable_vblank, .enable_vblank = atmel_hlcdc_crtc_enable_vblank,
.disable_vblank = atmel_hlcdc_crtc_disable_vblank, .disable_vblank = atmel_hlcdc_crtc_disable_vblank,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
}; };
int atmel_hlcdc_crtc_create(struct drm_device *dev) int atmel_hlcdc_crtc_create(struct drm_device *dev)

View File

@@ -3508,76 +3508,6 @@ fail:
} }
EXPORT_SYMBOL(drm_atomic_helper_page_flip_target); EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
/**
* drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table
* @crtc: CRTC object
* @red: red correction table
* @green: green correction table
* @blue: green correction table
* @size: size of the tables
* @ctx: lock acquire context
*
* Implements support for legacy gamma correction table for drivers
* that support color management through the DEGAMMA_LUT/GAMMA_LUT
* properties. See drm_crtc_enable_color_mgmt() and the containing chapter for
* how the atomic color management and gamma tables work.
*/
int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
u16 *red, u16 *green, u16 *blue,
uint32_t size,
struct drm_modeset_acquire_ctx *ctx)
{
struct drm_device *dev = crtc->dev;
struct drm_atomic_state *state;
struct drm_crtc_state *crtc_state;
struct drm_property_blob *blob = NULL;
struct drm_color_lut *blob_data;
int i, ret = 0;
bool replaced;
state = drm_atomic_state_alloc(crtc->dev);
if (!state)
return -ENOMEM;
blob = drm_property_create_blob(dev,
sizeof(struct drm_color_lut) * size,
NULL);
if (IS_ERR(blob)) {
ret = PTR_ERR(blob);
blob = NULL;
goto fail;
}
/* Prepare GAMMA_LUT with the legacy values. */
blob_data = blob->data;
for (i = 0; i < size; i++) {
blob_data[i].red = red[i];
blob_data[i].green = green[i];
blob_data[i].blue = blue[i];
}
state->acquire_ctx = ctx;
crtc_state = drm_atomic_get_crtc_state(state, crtc);
if (IS_ERR(crtc_state)) {
ret = PTR_ERR(crtc_state);
goto fail;
}
/* Reset DEGAMMA_LUT and CTM properties. */
replaced = drm_property_replace_blob(&crtc_state->degamma_lut, NULL);
replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob);
crtc_state->color_mgmt_changed |= replaced;
ret = drm_atomic_commit(state);
fail:
drm_atomic_state_put(state);
drm_property_blob_put(blob);
return ret;
}
EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
/** /**
* drm_atomic_helper_bridge_propagate_bus_fmt() - Propagate output format to * drm_atomic_helper_bridge_propagate_bus_fmt() - Propagate output format to
* the input end of a bridge * the input end of a bridge

View File

@@ -22,6 +22,7 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <drm/drm_atomic.h>
#include <drm/drm_color_mgmt.h> #include <drm/drm_color_mgmt.h>
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_device.h> #include <drm/drm_device.h>
@@ -89,9 +90,8 @@
* modes) appropriately. * modes) appropriately.
* *
* There is also support for a legacy gamma table, which is set up by calling * There is also support for a legacy gamma table, which is set up by calling
* drm_mode_crtc_set_gamma_size(). Drivers which support both should use * drm_mode_crtc_set_gamma_size(). The DRM core will then alias the legacy gamma
* drm_atomic_helper_legacy_gamma_set() to alias the legacy gamma ramp with the * ramp with "GAMMA_LUT".
* "GAMMA_LUT" property above.
* *
* Support for different non RGB color encodings is controlled through * Support for different non RGB color encodings is controlled through
* &drm_plane specific COLOR_ENCODING and COLOR_RANGE properties. They * &drm_plane specific COLOR_ENCODING and COLOR_RANGE properties. They
@@ -156,9 +156,6 @@ EXPORT_SYMBOL(drm_color_ctm_s31_32_to_qm_n);
* optional. The gamma and degamma properties are only attached if * optional. The gamma and degamma properties are only attached if
* their size is not 0 and ctm_property is only attached if has_ctm is * their size is not 0 and ctm_property is only attached if has_ctm is
* true. * true.
*
* Drivers should use drm_atomic_helper_legacy_gamma_set() to implement the
* legacy &drm_crtc_funcs.gamma_set callback.
*/ */
void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
uint degamma_lut_size, uint degamma_lut_size,
@@ -231,6 +228,102 @@ int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
} }
EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size); EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size);
/**
* drm_crtc_supports_legacy_gamma - does the crtc support legacy gamma correction table
* @crtc: CRTC object
*
* Returns true/false if the given crtc supports setting the legacy gamma
* correction table.
*/
static bool drm_crtc_supports_legacy_gamma(struct drm_crtc *crtc)
{
u32 gamma_id = crtc->dev->mode_config.gamma_lut_property->base.id;
if (!crtc->gamma_size)
return false;
if (crtc->funcs->gamma_set)
return true;
return !!drm_mode_obj_find_prop_id(&crtc->base, gamma_id);
}
/**
* drm_crtc_legacy_gamma_set - set the legacy gamma correction table
* @crtc: CRTC object
* @red: red correction table
* @green: green correction table
* @blue: green correction table
* @size: size of the tables
* @ctx: lock acquire context
*
* Implements support for legacy gamma correction table for drivers
* that have set drm_crtc_funcs.gamma_set or that support color management
* through the DEGAMMA_LUT/GAMMA_LUT properties. See
* drm_crtc_enable_color_mgmt() and the containing chapter for
* how the atomic color management and gamma tables work.
*
* This function sets the gamma using drm_crtc_funcs.gamma_set if set, or
* alternatively using crtc color management properties.
*/
static int drm_crtc_legacy_gamma_set(struct drm_crtc *crtc,
u16 *red, u16 *green, u16 *blue,
u32 size,
struct drm_modeset_acquire_ctx *ctx)
{
struct drm_device *dev = crtc->dev;
struct drm_atomic_state *state;
struct drm_crtc_state *crtc_state;
struct drm_property_blob *blob;
struct drm_color_lut *blob_data;
int i, ret = 0;
bool replaced;
if (crtc->funcs->gamma_set)
return crtc->funcs->gamma_set(crtc, red, green, blue, size, ctx);
state = drm_atomic_state_alloc(crtc->dev);
if (!state)
return -ENOMEM;
blob = drm_property_create_blob(dev,
sizeof(struct drm_color_lut) * size,
NULL);
if (IS_ERR(blob)) {
ret = PTR_ERR(blob);
blob = NULL;
goto fail;
}
/* Prepare GAMMA_LUT with the legacy values. */
blob_data = blob->data;
for (i = 0; i < size; i++) {
blob_data[i].red = red[i];
blob_data[i].green = green[i];
blob_data[i].blue = blue[i];
}
state->acquire_ctx = ctx;
crtc_state = drm_atomic_get_crtc_state(state, crtc);
if (IS_ERR(crtc_state)) {
ret = PTR_ERR(crtc_state);
goto fail;
}
/* Set GAMMA_LUT and reset DEGAMMA_LUT and CTM */
replaced = drm_property_replace_blob(&crtc_state->degamma_lut, NULL);
replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob);
crtc_state->color_mgmt_changed |= replaced;
ret = drm_atomic_commit(state);
fail:
drm_atomic_state_put(state);
drm_property_blob_put(blob);
return ret;
}
/** /**
* drm_mode_gamma_set_ioctl - set the gamma table * drm_mode_gamma_set_ioctl - set the gamma table
* @dev: DRM device * @dev: DRM device
@@ -262,7 +355,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
if (!crtc) if (!crtc)
return -ENOENT; return -ENOENT;
if (crtc->funcs->gamma_set == NULL) if (!drm_crtc_supports_legacy_gamma(crtc))
return -ENOSYS; return -ENOSYS;
/* memcpy into gamma store */ /* memcpy into gamma store */
@@ -290,8 +383,8 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
goto out; goto out;
} }
ret = crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, ret = drm_crtc_legacy_gamma_set(crtc, r_base, g_base, b_base,
crtc->gamma_size, &ctx); crtc->gamma_size, &ctx);
out: out:
DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);

View File

@@ -17267,7 +17267,6 @@ fail:
} }
#define INTEL_CRTC_FUNCS \ #define INTEL_CRTC_FUNCS \
.gamma_set = drm_atomic_helper_legacy_gamma_set, \
.set_config = drm_atomic_helper_set_config, \ .set_config = drm_atomic_helper_set_config, \
.destroy = intel_crtc_destroy, \ .destroy = intel_crtc_destroy, \
.page_flip = drm_atomic_helper_page_flip, \ .page_flip = drm_atomic_helper_page_flip, \

View File

@@ -774,8 +774,6 @@ static const struct drm_crtc_funcs ingenic_drm_crtc_funcs = {
.enable_vblank = ingenic_drm_enable_vblank, .enable_vblank = ingenic_drm_enable_vblank,
.disable_vblank = ingenic_drm_disable_vblank, .disable_vblank = ingenic_drm_disable_vblank,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
}; };
static const struct drm_plane_helper_funcs ingenic_drm_plane_helper_funcs = { static const struct drm_plane_helper_funcs ingenic_drm_plane_helper_funcs = {

View File

@@ -619,7 +619,6 @@ static const struct drm_crtc_funcs mtk_crtc_funcs = {
.reset = mtk_drm_crtc_reset, .reset = mtk_drm_crtc_reset,
.atomic_duplicate_state = mtk_drm_crtc_duplicate_state, .atomic_duplicate_state = mtk_drm_crtc_duplicate_state,
.atomic_destroy_state = mtk_drm_crtc_destroy_state, .atomic_destroy_state = mtk_drm_crtc_destroy_state,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.enable_vblank = mtk_drm_crtc_enable_vblank, .enable_vblank = mtk_drm_crtc_enable_vblank,
.disable_vblank = mtk_drm_crtc_disable_vblank, .disable_vblank = mtk_drm_crtc_disable_vblank,
}; };

View File

@@ -503,7 +503,6 @@ nv50_head_destroy(struct drm_crtc *crtc)
static const struct drm_crtc_funcs static const struct drm_crtc_funcs
nv50_head_func = { nv50_head_func = {
.reset = nv50_head_reset, .reset = nv50_head_reset,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.destroy = nv50_head_destroy, .destroy = nv50_head_destroy,
.set_config = drm_atomic_helper_set_config, .set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip, .page_flip = drm_atomic_helper_page_flip,
@@ -518,7 +517,6 @@ nv50_head_func = {
static const struct drm_crtc_funcs static const struct drm_crtc_funcs
nvd9_head_func = { nvd9_head_func = {
.reset = nv50_head_reset, .reset = nv50_head_reset,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.destroy = nv50_head_destroy, .destroy = nv50_head_destroy,
.set_config = drm_atomic_helper_set_config, .set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip, .page_flip = drm_atomic_helper_page_flip,

View File

@@ -741,7 +741,6 @@ static const struct drm_crtc_funcs omap_crtc_funcs = {
.set_config = drm_atomic_helper_set_config, .set_config = drm_atomic_helper_set_config,
.destroy = omap_crtc_destroy, .destroy = omap_crtc_destroy,
.page_flip = drm_atomic_helper_page_flip, .page_flip = drm_atomic_helper_page_flip,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.atomic_duplicate_state = omap_crtc_duplicate_state, .atomic_duplicate_state = omap_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
.atomic_set_property = omap_crtc_atomic_set_property, .atomic_set_property = omap_crtc_atomic_set_property,

View File

@@ -1144,7 +1144,6 @@ static const struct drm_crtc_funcs crtc_funcs_gen3 = {
.set_crc_source = rcar_du_crtc_set_crc_source, .set_crc_source = rcar_du_crtc_set_crc_source,
.verify_crc_source = rcar_du_crtc_verify_crc_source, .verify_crc_source = rcar_du_crtc_verify_crc_source,
.get_crc_sources = rcar_du_crtc_get_crc_sources, .get_crc_sources = rcar_du_crtc_get_crc_sources,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
}; };
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------

View File

@@ -1643,7 +1643,6 @@ static const struct drm_crtc_funcs vop_crtc_funcs = {
.disable_vblank = vop_crtc_disable_vblank, .disable_vblank = vop_crtc_disable_vblank,
.set_crc_source = vop_crtc_set_crc_source, .set_crc_source = vop_crtc_set_crc_source,
.verify_crc_source = vop_crtc_verify_crc_source, .verify_crc_source = vop_crtc_verify_crc_source,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
}; };
static void vop_fb_unref_worker(struct drm_flip_work *work, void *val) static void vop_fb_unref_worker(struct drm_flip_work *work, void *val)

View File

@@ -713,7 +713,6 @@ static const struct drm_crtc_funcs ltdc_crtc_funcs = {
.enable_vblank = ltdc_crtc_enable_vblank, .enable_vblank = ltdc_crtc_enable_vblank,
.disable_vblank = ltdc_crtc_disable_vblank, .disable_vblank = ltdc_crtc_disable_vblank,
.get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
}; };
/* /*

View File

@@ -871,7 +871,6 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = {
.reset = vc4_crtc_reset, .reset = vc4_crtc_reset,
.atomic_duplicate_state = vc4_crtc_duplicate_state, .atomic_duplicate_state = vc4_crtc_duplicate_state,
.atomic_destroy_state = vc4_crtc_destroy_state, .atomic_destroy_state = vc4_crtc_destroy_state,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.enable_vblank = vc4_enable_vblank, .enable_vblank = vc4_enable_vblank,
.disable_vblank = vc4_disable_vblank, .disable_vblank = vc4_disable_vblank,
.get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,

View File

@@ -382,7 +382,6 @@ static const struct drm_crtc_funcs vc4_txp_crtc_funcs = {
.reset = vc4_crtc_reset, .reset = vc4_crtc_reset,
.atomic_duplicate_state = vc4_crtc_duplicate_state, .atomic_duplicate_state = vc4_crtc_duplicate_state,
.atomic_destroy_state = vc4_crtc_destroy_state, .atomic_destroy_state = vc4_crtc_destroy_state,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.enable_vblank = vc4_txp_enable_vblank, .enable_vblank = vc4_txp_enable_vblank,
.disable_vblank = vc4_txp_disable_vblank, .disable_vblank = vc4_txp_disable_vblank,
}; };

View File

@@ -147,10 +147,6 @@ int drm_atomic_helper_page_flip_target(
uint32_t flags, uint32_t flags,
uint32_t target, uint32_t target,
struct drm_modeset_acquire_ctx *ctx); struct drm_modeset_acquire_ctx *ctx);
int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
u16 *red, u16 *green, u16 *blue,
uint32_t size,
struct drm_modeset_acquire_ctx *ctx);
/** /**
* drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC * drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC