Commit 9ba25915 authored by Alex Hung's avatar Alex Hung Committed by Simon Ser
Browse files

drm/amd/display: Add support for sRGB EOTF in DEGAM block



Expose one 1D curve colorop with support for
DRM_COLOROP_1D_CURVE_SRGB_EOTF and program HW to perform
the sRGB transform when the colorop is not in bypass.

With this change the following IGT test passes:
kms_colorop --run plane-XR30-XR30-srgb_eotf

The color pipeline now consists of a single colorop:
1. 1D curve colorop w/ sRGB EOTF

Signed-off-by: default avatarAlex Hung <alex.hung@amd.com>
Co-developed-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarHarry Wentland <harry.wentland@amd.com>
Reviewed-by: default avatarDaniel Stone <daniels@collabora.com>
Signed-off-by: default avatarSimon Ser <contact@emersion.fr>
Link: https://patch.msgid.link/20251115000237.3561250-29-alex.hung@amd.com
parent af755a79
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -39,7 +39,8 @@ AMDGPUDM = \
	amdgpu_dm_psr.o \
	amdgpu_dm_replay.o \
	amdgpu_dm_quirks.o \
	amdgpu_dm_wb.o
	amdgpu_dm_wb.o \
	amdgpu_dm_colorop.o

ifdef CONFIG_DRM_AMD_DC_FP
AMDGPUDM += dc_fpu.o
+86 −0
Original line number Diff line number Diff line
@@ -667,6 +667,18 @@ amdgpu_tf_to_dc_tf(enum amdgpu_transfer_function tf)
	}
}

static enum dc_transfer_func_predefined
amdgpu_colorop_tf_to_dc_tf(enum drm_colorop_curve_1d_type tf)
{
	switch (tf) {
	case DRM_COLOROP_1D_CURVE_SRGB_EOTF:
	case DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF:
		return TRANSFER_FUNCTION_SRGB;
	default:
		return TRANSFER_FUNCTION_LINEAR;
	}
}

static void __to_dc_lut3d_color(struct dc_rgb *rgb,
				const struct drm_color_lut lut,
				int bit_precision)
@@ -1177,6 +1189,59 @@ __set_dm_plane_degamma(struct drm_plane_state *plane_state,
	return 0;
}

static int
__set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
			     struct drm_colorop_state *colorop_state)
{
	struct dc_transfer_func *tf = &dc_plane_state->in_transfer_func;
	struct drm_colorop *colorop = colorop_state->colorop;
	struct drm_device *drm = colorop->dev;

	if (colorop->type != DRM_COLOROP_1D_CURVE ||
	    colorop_state->curve_1d_type != DRM_COLOROP_1D_CURVE_SRGB_EOTF)
		return -EINVAL;

	if (colorop_state->bypass) {
		tf->type = TF_TYPE_BYPASS;
		tf->tf = TRANSFER_FUNCTION_LINEAR;
		return 0;
	}

	drm_dbg(drm, "Degamma colorop with ID: %d\n", colorop->base.id);

	tf->type = TF_TYPE_PREDEFINED;
	tf->tf = amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);

	return 0;
}

static int
__set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
			       struct dc_plane_state *dc_plane_state,
			       struct drm_colorop *colorop)
{
	struct drm_colorop *old_colorop;
	struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
	struct drm_atomic_state *state = plane_state->state;
	int i = 0;

	old_colorop = colorop;

	/* 1st op: 1d curve - degamma */
	for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
		if (new_colorop_state->colorop == old_colorop &&
		    new_colorop_state->curve_1d_type == DRM_COLOROP_1D_CURVE_SRGB_EOTF) {
			colorop_state = new_colorop_state;
			break;
		}
	}

	if (!colorop_state)
		return -EINVAL;

	return __set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state);
}

static int
amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
				     struct dc_plane_state *dc_plane_state)
@@ -1227,6 +1292,24 @@ amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
	return 0;
}

static int
amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
				       struct dc_plane_state *dc_plane_state)
{
	struct drm_colorop *colorop = plane_state->color_pipeline;
	int ret;

	/* 1D Curve - DEGAM TF */
	if (!colorop)
		return -EINVAL;

	ret = __set_dm_plane_colorop_degamma(plane_state, dc_plane_state, colorop);
	if (ret)
		return ret;

	return 0;
}

/**
 * amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC plane.
 * @crtc: amdgpu_dm crtc state
@@ -1323,5 +1406,8 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
		dc_plane_state->input_csc_color_matrix.enable_adjustment = false;
	}

	if (!amdgpu_dm_plane_set_colorop_properties(plane_state, dc_plane_state))
		return 0;

	return amdgpu_dm_plane_set_color_properties(plane_state, dc_plane_state);
}
+71 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: MIT
/*
 * Copyright 2023 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: AMD
 *
 */

#include <drm/drm_print.h>
#include <drm/drm_plane.h>
#include <drm/drm_property.h>
#include <drm/drm_colorop.h>

#include "amdgpu_dm_colorop.h"

const u64 amdgpu_dm_supported_degam_tfs =
	BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF);

#define MAX_COLOR_PIPELINE_OPS 10

int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
{
	struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
	struct drm_device *dev = plane->dev;
	int ret;
	int i = 0;

	memset(ops, 0, sizeof(ops));

	/* 1D curve - DEGAM TF */
	ops[i] = kzalloc(sizeof(*ops[0]), GFP_KERNEL);
	if (!ops[i]) {
		ret = -ENOMEM;
		goto cleanup;
	}

	ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane, amdgpu_dm_supported_degam_tfs);
	if (ret)
		goto cleanup;

	list->type = ops[i]->base.id;
	list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[i]->base.id);

	return 0;

cleanup:
	if (ret == -ENOMEM)
		drm_err(plane->dev, "KMS: Failed to allocate colorop\n");

	drm_colorop_pipeline_destroy(dev);

	return ret;
}
+34 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: MIT */
/*
 * Copyright 2023 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: AMD
 *
 */

#ifndef __AMDGPU_DM_COLOROP_H__
#define __AMDGPU_DM_COLOROP_H__

extern const u64 amdgpu_dm_supported_degam_tfs;

int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list);

#endif /* __AMDGPU_DM_COLOROP_H__*/
+18 −2
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include "amdgpu_display.h"
#include "amdgpu_dm_trace.h"
#include "amdgpu_dm_plane.h"
#include "amdgpu_dm_colorop.h"
#include "gc/gc_11_0_0_offset.h"
#include "gc/gc_11_0_0_sh_mask.h"

@@ -1790,13 +1791,28 @@ static int
dm_plane_init_colorops(struct drm_plane *plane)
{
	struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
	struct drm_device *dev = plane->dev;
	struct amdgpu_device *adev = drm_to_adev(dev);
	struct dc *dc = adev->dm.dc;
	int len = 0;
	int ret;

	if (plane->type == DRM_PLANE_TYPE_CURSOR)
		return 0;

	/* initialize pipeline */
	if (dc->ctx->dce_version >= DCN_VERSION_3_0) {
		ret = amdgpu_dm_initialize_default_pipeline(plane, &pipelines[len]);
		if (ret) {
			drm_err(plane->dev, "Failed to create color pipeline for plane %d: %d\n",
				plane->base.id, ret);
			return ret;
		}
		len++;

		/* Create COLOR_PIPELINE property and attach */
		drm_plane_create_color_pipeline_property(plane, pipelines, len);
	}

	return 0;
}