Skip to content

Commit

Permalink
drm: automatic legacy gamma support
Browse files Browse the repository at this point in the history
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.

Add two functions: drm_crtc_supports_legacy_gamma() which tells if the
legacy gamma table can be set, and drm_crtc_legacy_gamma_set() which
does the work by either calling the drm_crtc_funcs.gamma_set or using
GAMMA_LUT or DEGAMMA_LUT.

We can then drop drm_atomic_helper_legacy_gamma_set() and remove all its
uses.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
  • Loading branch information
tomba authored and intel-lab-lkp committed Dec 8, 2020
1 parent 3b3bd66 commit 82a704a
Show file tree
Hide file tree
Showing 21 changed files with 122 additions and 116 deletions.
1 change: 0 additions & 1 deletion drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
Original file line number Diff line number Diff line change
Expand Up @@ -4910,7 +4910,6 @@ static void dm_disable_vblank(struct drm_crtc *crtc)
static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
.reset = dm_crtc_reset_state,
.destroy = amdgpu_dm_crtc_destroy,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.atomic_duplicate_state = dm_crtc_duplicate_state,
Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,6 @@ static void komeda_crtc_vblank_disable(struct drm_crtc *crtc)
}

static const struct drm_crtc_funcs komeda_crtc_funcs = {
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/arm/malidp_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,6 @@ static void malidp_crtc_disable_vblank(struct drm_crtc *crtc)
}

static const struct drm_crtc_funcs malidp_crtc_funcs = {
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/armada/armada_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,6 @@ static const struct drm_crtc_funcs armada_crtc_funcs = {
.cursor_set = armada_drm_crtc_cursor_set,
.cursor_move = armada_drm_crtc_cursor_move,
.destroy = armada_drm_crtc_destroy,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/ast/ast_mode.c
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,6 @@ static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc,

static const struct drm_crtc_funcs ast_crtc_funcs = {
.reset = ast_crtc_reset,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,6 @@ static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = {
.atomic_destroy_state = atmel_hlcdc_crtc_destroy_state,
.enable_vblank = atmel_hlcdc_crtc_enable_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)
Expand Down
79 changes: 0 additions & 79 deletions drivers/gpu/drm/drm_atomic_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -3499,85 +3499,6 @@ int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc,
}
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.
*
* This function uses the GAMMA_LUT or DEGAMMA_LUT property for the gamma table.
* GAMMA_LUT property is used if it exists, and DEGAMMA_LUT property is used as
* a fallback.
*/
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;

if (!crtc->has_gamma_prop && !crtc->has_degamma_prop)
return -ENODEV;

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/DEGAMMA_LUT and reset DEGAMMA/GAMMA_LUT and CTM */
replaced = drm_property_replace_blob(&crtc_state->degamma_lut,
crtc->has_gamma_prop ? NULL : blob);
replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
replaced |= drm_property_replace_blob(&crtc_state->gamma_lut,
crtc->has_gamma_prop ? blob : NULL);
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
* the input end of a bridge
Expand Down
118 changes: 109 additions & 9 deletions drivers/gpu/drm/drm_color_mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include <linux/uaccess.h>

#include <drm/drm_atomic.h>
#include <drm/drm_color_mgmt.h>
#include <drm/drm_crtc.h>
#include <drm/drm_device.h>
Expand Down Expand Up @@ -89,9 +90,8 @@
* modes) appropriately.
*
* 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_atomic_helper_legacy_gamma_set() to alias the legacy gamma ramp with the
* "GAMMA_LUT" property above.
* drm_mode_crtc_set_gamma_size(). The DRM core will then alias the legacy gamma
* ramp with "GAMMA_LUT", or if that is unavailable "DEGAMMA_LUT".
*
* Support for different non RGB color encodings is controlled through
* &drm_plane specific COLOR_ENCODING and COLOR_RANGE properties. They
Expand Down Expand Up @@ -156,9 +156,6 @@ EXPORT_SYMBOL(drm_color_ctm_s31_32_to_qm_n);
* 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
* 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,
uint degamma_lut_size,
Expand Down Expand Up @@ -235,6 +232,109 @@ int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
}
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.
*/
bool drm_crtc_supports_legacy_gamma(struct drm_crtc *crtc)
{
if (!crtc->gamma_size)
return false;

if (crtc->funcs->gamma_set)
return true;

return crtc->has_gamma_prop || crtc->has_degamma_prop;
}
EXPORT_SYMBOL(drm_crtc_supports_legacy_gamma);

/**
* 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 the first one available:
* - drm_crtc_funcs.gamma_set()
* - GAMMA_LUT
* - DEGAMMA_LUT
*/
int drm_crtc_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;

if (crtc->funcs->gamma_set)
return crtc->funcs->gamma_set(crtc, red, green, blue, size, ctx);

if (!crtc->has_gamma_prop && !crtc->has_degamma_prop)
return -ENODEV;

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/DEGAMMA_LUT and reset DEGAMMA/GAMMA_LUT and CTM */
replaced = drm_property_replace_blob(&crtc_state->degamma_lut,
crtc->has_gamma_prop ? NULL : blob);
replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
replaced |= drm_property_replace_blob(&crtc_state->gamma_lut,
crtc->has_gamma_prop ? blob : NULL);
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_crtc_legacy_gamma_set);

/**
* drm_mode_gamma_set_ioctl - set the gamma table
* @dev: DRM device
Expand Down Expand Up @@ -266,7 +366,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
if (!crtc)
return -ENOENT;

if (crtc->funcs->gamma_set == NULL)
if (!drm_crtc_supports_legacy_gamma(crtc))
return -ENOSYS;

/* memcpy into gamma store */
Expand Down Expand Up @@ -294,8 +394,8 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
goto out;
}

ret = crtc->funcs->gamma_set(crtc, r_base, g_base, b_base,
crtc->gamma_size, &ctx);
ret = drm_crtc_legacy_gamma_set(crtc, r_base, g_base, b_base,
crtc->gamma_size, &ctx);

out:
DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/drm_crtc_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
const char *drm_get_color_encoding_name(enum drm_color_encoding encoding);
const char *drm_get_color_range_name(enum drm_color_range range);

bool drm_crtc_supports_legacy_gamma(struct drm_crtc *crtc);
int drm_crtc_legacy_gamma_set(struct drm_crtc *crtc,
u16 *red, u16 *green, u16 *blue,
uint32_t size,
struct drm_modeset_acquire_ctx *ctx);

/* IOCTLs */
int drm_mode_gamma_get_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
Expand Down
13 changes: 7 additions & 6 deletions drivers/gpu/drm/drm_fb_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>

#include "drm_crtc_internal.h"
#include "drm_crtc_helper_internal.h"
#include "drm_internal.h"

Expand Down Expand Up @@ -136,15 +137,15 @@ static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc)
{
uint16_t *r_base, *g_base, *b_base;

if (crtc->funcs->gamma_set == NULL)
if (!drm_crtc_supports_legacy_gamma(crtc))
return;

r_base = crtc->gamma_store;
g_base = r_base + crtc->gamma_size;
b_base = g_base + crtc->gamma_size;

crtc->funcs->gamma_set(crtc, r_base, g_base, b_base,
crtc->gamma_size, NULL);
drm_crtc_legacy_gamma_set(crtc, r_base, g_base, b_base,
crtc->gamma_size, NULL);
}

/**
Expand Down Expand Up @@ -907,7 +908,7 @@ static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info)
drm_modeset_lock_all(fb_helper->dev);
drm_client_for_each_modeset(modeset, &fb_helper->client) {
crtc = modeset->crtc;
if (!crtc->funcs->gamma_set || !crtc->gamma_size)
if (!drm_crtc_supports_legacy_gamma(crtc))
return -EINVAL;

if (cmap->start + cmap->len > crtc->gamma_size)
Expand All @@ -921,8 +922,8 @@ static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info)
memcpy(g + cmap->start, cmap->green, cmap->len * sizeof(*g));
memcpy(b + cmap->start, cmap->blue, cmap->len * sizeof(*b));

ret = crtc->funcs->gamma_set(crtc, r, g, b,
crtc->gamma_size, NULL);
ret = drm_crtc_legacy_gamma_set(crtc, r, g, b, crtc->gamma_size,
NULL);
if (ret)
return ret;
}
Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/i915/display/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -17273,7 +17273,6 @@ static int intel_crtc_late_register(struct drm_crtc *crtc)
}

#define INTEL_CRTC_FUNCS \
.gamma_set = drm_atomic_helper_legacy_gamma_set, \
.set_config = drm_atomic_helper_set_config, \
.destroy = intel_crtc_destroy, \
.page_flip = drm_atomic_helper_page_flip, \
Expand Down
2 changes: 0 additions & 2 deletions drivers/gpu/drm/ingenic/ingenic-drm-drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -746,8 +746,6 @@ static const struct drm_crtc_funcs ingenic_drm_crtc_funcs = {

.enable_vblank = ingenic_drm_enable_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 = {
Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/mediatek/mtk_drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,6 @@ static const struct drm_crtc_funcs mtk_crtc_funcs = {
.reset = mtk_drm_crtc_reset,
.atomic_duplicate_state = mtk_drm_crtc_duplicate_state,
.atomic_destroy_state = mtk_drm_crtc_destroy_state,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.enable_vblank = mtk_drm_crtc_enable_vblank,
.disable_vblank = mtk_drm_crtc_disable_vblank,
};
Expand Down
2 changes: 0 additions & 2 deletions drivers/gpu/drm/nouveau/dispnv50/head.c
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,6 @@ nv50_head_destroy(struct drm_crtc *crtc)
static const struct drm_crtc_funcs
nv50_head_func = {
.reset = nv50_head_reset,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.destroy = nv50_head_destroy,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
Expand All @@ -513,7 +512,6 @@ nv50_head_func = {
static const struct drm_crtc_funcs
nvd9_head_func = {
.reset = nv50_head_reset,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.destroy = nv50_head_destroy,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
Expand Down

0 comments on commit 82a704a

Please sign in to comment.