linux/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c

// SPDX-License-Identifier: MIT
/*
 * Copyright 2022 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_atomic_helper.h>
#include <drm/drm_blend.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_fourcc.h>

#include "amdgpu.h"
#include "dal_asic_id.h"
#include "amdgpu_display.h"
#include "amdgpu_dm_trace.h"
#include "amdgpu_dm_plane.h"
#include "gc/gc_11_0_0_offset.h"
#include "gc/gc_11_0_0_sh_mask.h"

/*
 * TODO: these are currently initialized to rgb formats only.
 * For future use cases we should either initialize them dynamically based on
 * plane capabilities, or initialize this array to all formats, so internal drm
 * check will succeed, and let DC implement proper check
 */
static const uint32_t rgb_formats[] =;

static const uint32_t overlay_formats[] =;

static const uint32_t video_formats[] =;

static const u32 cursor_formats[] =;

enum dm_micro_swizzle {};

const struct drm_format_info *amdgpu_dm_plane_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
{}

void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state *plane_state,
			       bool *per_pixel_alpha, bool *pre_multiplied_alpha,
			       bool *global_alpha, int *global_alpha_value)
{}

static void amdgpu_dm_plane_add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_t mod)
{}

static bool amdgpu_dm_plane_modifier_has_dcc(uint64_t modifier)
{}

static unsigned int amdgpu_dm_plane_modifier_gfx9_swizzle_mode(uint64_t modifier)
{}

static void amdgpu_dm_plane_fill_gfx8_tiling_info_from_flags(union dc_tiling_info *tiling_info,
							     uint64_t tiling_flags)
{}

static void amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(const struct amdgpu_device *adev,
							      union dc_tiling_info *tiling_info)
{}

static void amdgpu_dm_plane_fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev,
								union dc_tiling_info *tiling_info,
								uint64_t modifier)
{}

static int amdgpu_dm_plane_validate_dcc(struct amdgpu_device *adev,
					const enum surface_pixel_format format,
					const enum dc_rotation_angle rotation,
					const union dc_tiling_info *tiling_info,
					const struct dc_plane_dcc_param *dcc,
					const struct dc_plane_address *address,
					const struct plane_size *plane_size)
{}

static int amdgpu_dm_plane_fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
								     const struct amdgpu_framebuffer *afb,
								     const enum surface_pixel_format format,
								     const enum dc_rotation_angle rotation,
								     const struct plane_size *plane_size,
								     union dc_tiling_info *tiling_info,
								     struct dc_plane_dcc_param *dcc,
								     struct dc_plane_address *address,
								     const bool force_disable_dcc)
{}

static int amdgpu_dm_plane_fill_gfx12_plane_attributes_from_modifiers(struct amdgpu_device *adev,
								      const struct amdgpu_framebuffer *afb,
								      const enum surface_pixel_format format,
								      const enum dc_rotation_angle rotation,
								      const struct plane_size *plane_size,
								      union dc_tiling_info *tiling_info,
								      struct dc_plane_dcc_param *dcc,
								      struct dc_plane_address *address,
								      const bool force_disable_dcc)
{}

static void amdgpu_dm_plane_add_gfx10_1_modifiers(const struct amdgpu_device *adev,
						  uint64_t **mods,
						  uint64_t *size,
						  uint64_t *capacity)
{}

static void amdgpu_dm_plane_add_gfx9_modifiers(const struct amdgpu_device *adev,
					       uint64_t **mods,
					       uint64_t *size,
					       uint64_t *capacity)
{}

static void amdgpu_dm_plane_add_gfx10_3_modifiers(const struct amdgpu_device *adev,
						  uint64_t **mods,
						  uint64_t *size,
						  uint64_t *capacity)
{}

static void amdgpu_dm_plane_add_gfx11_modifiers(struct amdgpu_device *adev,
		      uint64_t **mods, uint64_t *size, uint64_t *capacity)
{}

static void amdgpu_dm_plane_add_gfx12_modifiers(struct amdgpu_device *adev,
		      uint64_t **mods, uint64_t *size, uint64_t *capacity)
{}

static int amdgpu_dm_plane_get_plane_modifiers(struct amdgpu_device *adev, unsigned int plane_type, uint64_t **mods)
{}

static int amdgpu_dm_plane_get_plane_formats(const struct drm_plane *plane,
					     const struct dc_plane_cap *plane_cap,
					     uint32_t *formats, int max_formats)
{}

int amdgpu_dm_plane_fill_plane_buffer_attributes(struct amdgpu_device *adev,
			     const struct amdgpu_framebuffer *afb,
			     const enum surface_pixel_format format,
			     const enum dc_rotation_angle rotation,
			     const uint64_t tiling_flags,
			     union dc_tiling_info *tiling_info,
			     struct plane_size *plane_size,
			     struct dc_plane_dcc_param *dcc,
			     struct dc_plane_address *address,
			     bool tmz_surface,
			     bool force_disable_dcc)
{}

static int amdgpu_dm_plane_helper_prepare_fb(struct drm_plane *plane,
					     struct drm_plane_state *new_state)
{}

static void amdgpu_dm_plane_helper_cleanup_fb(struct drm_plane *plane,
					      struct drm_plane_state *old_state)
{}

static void amdgpu_dm_plane_get_min_max_dc_plane_scaling(struct drm_device *dev,
					 struct drm_framebuffer *fb,
					 int *min_downscale, int *max_upscale)
{}

int amdgpu_dm_plane_helper_check_state(struct drm_plane_state *state,
				       struct drm_crtc_state *new_crtc_state)
{}

int amdgpu_dm_plane_fill_dc_scaling_info(struct amdgpu_device *adev,
				const struct drm_plane_state *state,
				struct dc_scaling_info *scaling_info)
{}

static int amdgpu_dm_plane_atomic_check(struct drm_plane *plane,
					struct drm_atomic_state *state)
{}

static int amdgpu_dm_plane_atomic_async_check(struct drm_plane *plane,
					      struct drm_atomic_state *state)
{}

int amdgpu_dm_plane_get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc,
					struct dc_cursor_position *position)
{}

void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
				 struct drm_plane_state *old_plane_state)
{}

static void amdgpu_dm_plane_atomic_async_update(struct drm_plane *plane,
						struct drm_atomic_state *state)
{}

static const struct drm_plane_helper_funcs dm_plane_helper_funcs =;

static void amdgpu_dm_plane_drm_plane_reset(struct drm_plane *plane)
{}

static struct drm_plane_state *amdgpu_dm_plane_drm_plane_duplicate_state(struct drm_plane *plane)
{}

static bool amdgpu_dm_plane_format_mod_supported(struct drm_plane *plane,
						 uint32_t format,
						 uint64_t modifier)
{}

static void amdgpu_dm_plane_drm_plane_destroy_state(struct drm_plane *plane,
						    struct drm_plane_state *state)
{}

#ifdef AMD_PRIVATE_COLOR
static void
dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
					     struct drm_plane *plane)
{
	struct amdgpu_mode_info mode_info = dm->adev->mode_info;
	struct dpp_color_caps dpp_color_caps = dm->dc->caps.color.dpp;

	/* Check HW color pipeline capabilities on DPP block (pre-blending)
	 * before exposing related properties.
	 */
	if (dpp_color_caps.dgam_ram || dpp_color_caps.gamma_corr) {
		drm_object_attach_property(&plane->base,
					   mode_info.plane_degamma_lut_property,
					   0);
		drm_object_attach_property(&plane->base,
					   mode_info.plane_degamma_lut_size_property,
					   MAX_COLOR_LUT_ENTRIES);
		drm_object_attach_property(&plane->base,
					   dm->adev->mode_info.plane_degamma_tf_property,
					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
	}
	/* HDR MULT is always available */
	drm_object_attach_property(&plane->base,
				   dm->adev->mode_info.plane_hdr_mult_property,
				   AMDGPU_HDR_MULT_DEFAULT);

	/* Only enable plane CTM if both DPP and MPC gamut remap is available. */
	if (dm->dc->caps.color.mpc.gamut_remap)
		drm_object_attach_property(&plane->base,
					   dm->adev->mode_info.plane_ctm_property, 0);

	if (dpp_color_caps.hw_3d_lut) {
		drm_object_attach_property(&plane->base,
					   mode_info.plane_shaper_lut_property, 0);
		drm_object_attach_property(&plane->base,
					   mode_info.plane_shaper_lut_size_property,
					   MAX_COLOR_LUT_ENTRIES);
		drm_object_attach_property(&plane->base,
					   mode_info.plane_shaper_tf_property,
					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
		drm_object_attach_property(&plane->base,
					   mode_info.plane_lut3d_property, 0);
		drm_object_attach_property(&plane->base,
					   mode_info.plane_lut3d_size_property,
					   MAX_COLOR_3DLUT_SIZE);
	}

	if (dpp_color_caps.ogam_ram) {
		drm_object_attach_property(&plane->base,
					   mode_info.plane_blend_lut_property, 0);
		drm_object_attach_property(&plane->base,
					   mode_info.plane_blend_lut_size_property,
					   MAX_COLOR_LUT_ENTRIES);
		drm_object_attach_property(&plane->base,
					   mode_info.plane_blend_tf_property,
					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
	}
}

static int
dm_atomic_plane_set_property(struct drm_plane *plane,
			     struct drm_plane_state *state,
			     struct drm_property *property,
			     uint64_t val)
{
	struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
	struct amdgpu_device *adev = drm_to_adev(plane->dev);
	bool replaced = false;
	int ret;

	if (property == adev->mode_info.plane_degamma_lut_property) {
		ret = drm_property_replace_blob_from_id(plane->dev,
							&dm_plane_state->degamma_lut,
							val, -1,
							sizeof(struct drm_color_lut),
							&replaced);
		dm_plane_state->base.color_mgmt_changed |= replaced;
		return ret;
	} else if (property == adev->mode_info.plane_degamma_tf_property) {
		if (dm_plane_state->degamma_tf != val) {
			dm_plane_state->degamma_tf = val;
			dm_plane_state->base.color_mgmt_changed = 1;
		}
	} else if (property == adev->mode_info.plane_hdr_mult_property) {
		if (dm_plane_state->hdr_mult != val) {
			dm_plane_state->hdr_mult = val;
			dm_plane_state->base.color_mgmt_changed = 1;
		}
	} else if (property == adev->mode_info.plane_ctm_property) {
		ret = drm_property_replace_blob_from_id(plane->dev,
							&dm_plane_state->ctm,
							val,
							sizeof(struct drm_color_ctm_3x4), -1,
							&replaced);
		dm_plane_state->base.color_mgmt_changed |= replaced;
		return ret;
	} else if (property == adev->mode_info.plane_shaper_lut_property) {
		ret = drm_property_replace_blob_from_id(plane->dev,
							&dm_plane_state->shaper_lut,
							val, -1,
							sizeof(struct drm_color_lut),
							&replaced);
		dm_plane_state->base.color_mgmt_changed |= replaced;
		return ret;
	} else if (property == adev->mode_info.plane_shaper_tf_property) {
		if (dm_plane_state->shaper_tf != val) {
			dm_plane_state->shaper_tf = val;
			dm_plane_state->base.color_mgmt_changed = 1;
		}
	} else if (property == adev->mode_info.plane_lut3d_property) {
		ret = drm_property_replace_blob_from_id(plane->dev,
							&dm_plane_state->lut3d,
							val, -1,
							sizeof(struct drm_color_lut),
							&replaced);
		dm_plane_state->base.color_mgmt_changed |= replaced;
		return ret;
	} else if (property == adev->mode_info.plane_blend_lut_property) {
		ret = drm_property_replace_blob_from_id(plane->dev,
							&dm_plane_state->blend_lut,
							val, -1,
							sizeof(struct drm_color_lut),
							&replaced);
		dm_plane_state->base.color_mgmt_changed |= replaced;
		return ret;
	} else if (property == adev->mode_info.plane_blend_tf_property) {
		if (dm_plane_state->blend_tf != val) {
			dm_plane_state->blend_tf = val;
			dm_plane_state->base.color_mgmt_changed = 1;
		}
	} else {
		drm_dbg_atomic(plane->dev,
			       "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
			       plane->base.id, plane->name,
			       property->base.id, property->name);
		return -EINVAL;
	}

	return 0;
}

static int
dm_atomic_plane_get_property(struct drm_plane *plane,
			     const struct drm_plane_state *state,
			     struct drm_property *property,
			     uint64_t *val)
{
	struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
	struct amdgpu_device *adev = drm_to_adev(plane->dev);

	if (property == adev->mode_info.plane_degamma_lut_property) {
		*val = (dm_plane_state->degamma_lut) ?
			dm_plane_state->degamma_lut->base.id : 0;
	} else if (property == adev->mode_info.plane_degamma_tf_property) {
		*val = dm_plane_state->degamma_tf;
	} else if (property == adev->mode_info.plane_hdr_mult_property) {
		*val = dm_plane_state->hdr_mult;
	} else if (property == adev->mode_info.plane_ctm_property) {
		*val = (dm_plane_state->ctm) ?
			dm_plane_state->ctm->base.id : 0;
	} else 	if (property == adev->mode_info.plane_shaper_lut_property) {
		*val = (dm_plane_state->shaper_lut) ?
			dm_plane_state->shaper_lut->base.id : 0;
	} else if (property == adev->mode_info.plane_shaper_tf_property) {
		*val = dm_plane_state->shaper_tf;
	} else 	if (property == adev->mode_info.plane_lut3d_property) {
		*val = (dm_plane_state->lut3d) ?
			dm_plane_state->lut3d->base.id : 0;
	} else 	if (property == adev->mode_info.plane_blend_lut_property) {
		*val = (dm_plane_state->blend_lut) ?
			dm_plane_state->blend_lut->base.id : 0;
	} else if (property == adev->mode_info.plane_blend_tf_property) {
		*val = dm_plane_state->blend_tf;

	} else {
		return -EINVAL;
	}

	return 0;
}
#endif

static const struct drm_plane_funcs dm_plane_funcs =;

int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
				struct drm_plane *plane,
				unsigned long possible_crtcs,
				const struct dc_plane_cap *plane_cap)
{}

bool amdgpu_dm_plane_is_video_format(uint32_t format)
{}