Commit 6fbefb84 authored by Harry Wentland's avatar Harry Wentland Committed by Alex Deucher

drm/amd/display: Add DC core changes for DCN2

Core DC changes for DCN2.
Signed-off-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 7ed4e635
......@@ -25,6 +25,12 @@
DC_LIBS = basics bios calcs clk_mgr dce gpio irq virtual
ifdef CONFIG_DRM_AMD_DC_DCN2_0
DC_LIBS += dcn20
endif
ifdef CONFIG_DRM_AMD_DC_DCN1_0
DC_LIBS += dcn10 dml
endif
......
......@@ -56,6 +56,10 @@
#include "dc_link_dp.h"
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
#include "vm_helper.h"
#endif
#include "dce/dce_i2c.h"
#define DC_LOGGER \
......@@ -528,6 +532,11 @@ static void destruct(struct dc *dc)
kfree(dc->dcn_ip);
dc->dcn_ip = NULL;
#endif
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
kfree(dc->vm_helper);
dc->vm_helper = NULL;
#endif
}
......@@ -545,6 +554,11 @@ static bool construct(struct dc *dc,
enum dce_version dc_version = DCE_VERSION_UNKNOWN;
dc->config = init_params->flags;
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
// Allocate memory for the vm_helper
dc->vm_helper = kzalloc(sizeof(struct vm_helper), GFP_KERNEL);
#endif
memcpy(&dc->bb_overrides, &init_params->bb_overrides, sizeof(dc->bb_overrides));
dc_dceip = kzalloc(sizeof(*dc_dceip), GFP_KERNEL);
......@@ -578,6 +592,9 @@ static bool construct(struct dc *dc,
}
dc->dcn_ip = dcn_ip;
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
dc->soc_bounding_box = init_params->soc_bounding_box;
#endif
#endif
dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL);
......@@ -674,6 +691,21 @@ static bool construct(struct dc *dc,
return false;
}
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
static bool disable_all_writeback_pipes_for_stream(
const struct dc *dc,
struct dc_stream_state *stream,
struct dc_state *context)
{
int i;
for (i = 0; i < stream->num_wb_info; i++)
stream->writeback_info[i].wb_enabled = false;
return true;
}
#endif
static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
{
int i, j;
......@@ -698,6 +730,9 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
}
if (should_disable && old_stream) {
dc_rem_all_planes_for_stream(dc, old_stream, dangling_context);
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context);
#endif
dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context);
}
}
......@@ -769,6 +804,26 @@ void dc_destroy(struct dc **dc)
*dc = NULL;
}
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
bool dc_init_memory_hub(struct dc *dc, struct dc_addr_space_config *config)
{
// Memory hub init isn't done as part of dc_create because in windows, dal/dc is
// constructed before the vm config is setup in kmd so there's no way
// they can give it to us at boot/dc_create
bool vmSupported;
// Call HWSS to setup HUBBUB for address config
dc->hwss.init_dchub(dc->hwseq, dc, config);
// Pre-init system aperture start/end for all HUBP instances (if not gating?)
// or cache system aperture if using power gating
memcpy(&dc->vm_config, config, sizeof(struct dc_addr_space_config));
vmSupported = (dc->ctx->asic_id.chip_family == FAMILY_NV) ? true : false;
return vmSupported;
}
#endif
static void enable_timing_multisync(
struct dc *dc,
struct dc_state *ctx)
......@@ -1598,6 +1653,19 @@ static void copy_surface_update_to_plane(
sizeof(struct dc_transfer_func_distributed_points));
}
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
if (srf_update->func_shaper &&
(surface->in_shaper_func !=
srf_update->func_shaper))
memcpy(surface->in_shaper_func, srf_update->func_shaper,
sizeof(*surface->in_shaper_func));
if (srf_update->lut3d_func &&
(surface->lut3d_func !=
srf_update->lut3d_func))
memcpy(surface->lut3d_func, srf_update->lut3d_func,
sizeof(*surface->lut3d_func));
#endif
if (srf_update->input_csc_color_matrix)
surface->input_csc_color_matrix =
*srf_update->input_csc_color_matrix;
......@@ -1646,11 +1714,20 @@ static void commit_planes_do_stream_update(struct dc *dc,
dc_stream_program_csc_matrix(dc, stream);
if (stream_update->dither_option) {
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
struct pipe_ctx *odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
#endif
resource_build_bit_depth_reduction_params(pipe_ctx->stream,
&pipe_ctx->stream->bit_depth_params);
pipe_ctx->stream_res.opp->funcs->opp_program_fmt(pipe_ctx->stream_res.opp,
&stream->bit_depth_params,
&stream->clamping);
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
if (odm_pipe)
odm_pipe->stream_res.opp->funcs->opp_program_fmt(odm_pipe->stream_res.opp,
&stream->bit_depth_params,
&stream->clamping);
#endif
}
/* Full fe update*/
......@@ -1726,6 +1803,30 @@ static void commit_planes_for_stream(struct dc *dc,
return;
}
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
for (i = 0; i < surface_count; i++) {
struct dc_plane_state *plane_state = srf_updates[i].surface;
/*set logical flag for lock/unlock use*/
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
if (!pipe_ctx->plane_state)
continue;
if (pipe_ctx->plane_state != plane_state)
continue;
plane_state->triplebuffer_flips = false;
if (update_type == UPDATE_TYPE_FAST &&
dc->hwss.program_triplebuffer != NULL &&
!plane_state->flip_immediate &&
!dc->debug.disable_tri_buf) {
/*triple buffer for VUpdate only*/
plane_state->triplebuffer_flips = true;
}
}
}
}
#endif
// Update Type FULL, Surface updates
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
......@@ -1744,6 +1845,16 @@ static void commit_planes_for_stream(struct dc *dc,
if (update_type == UPDATE_TYPE_FAST)
continue;
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
ASSERT(!pipe_ctx->plane_state->triplebuffer_flips);
if (dc->hwss.program_triplebuffer != NULL &&
!dc->debug.disable_tri_buf) {
/*turn off triple buffer for full update*/
dc->hwss.program_triplebuffer(
dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips);
}
#endif
stream_status =
stream_get_status(context, pipe_ctx->stream);
......@@ -1760,7 +1871,8 @@ static void commit_planes_for_stream(struct dc *dc,
*/
dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true);
/* Perform requested Updates */
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
if (dc->hwss.set_flip_control_gsl)
for (i = 0; i < surface_count; i++) {
struct dc_plane_state *plane_state = srf_updates[i].surface;
......@@ -1773,6 +1885,33 @@ static void commit_planes_for_stream(struct dc *dc,
if (pipe_ctx->plane_state != plane_state)
continue;
// GSL has to be used for flip immediate
dc->hwss.set_flip_control_gsl(pipe_ctx,
plane_state->flip_immediate);
}
}
#endif
/* Perform requested Updates */
for (i = 0; i < surface_count; i++) {
struct dc_plane_state *plane_state = srf_updates[i].surface;
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
if (pipe_ctx->stream != stream)
continue;
if (pipe_ctx->plane_state != plane_state)
continue;
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
/*program triple buffer after lock based on flip type*/
if (dc->hwss.program_triplebuffer != NULL &&
!dc->debug.disable_tri_buf) {
/*only enable triplebuffer for fast_update*/
dc->hwss.program_triplebuffer(
dc, pipe_ctx, plane_state->triplebuffer_flips);
}
#endif
if (srf_updates[i].flip_addr)
dc->hwss.update_plane_addr(dc, pipe_ctx);
}
......
......@@ -43,6 +43,10 @@
#include "dpcd_defs.h"
#include "dmcu.h"
#include "hw/clk_mgr.h"
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
#include "resource.h"
#endif
#include "hw/clk_mgr.h"
#define DC_LOGGER_INIT(logger)
......@@ -1504,6 +1508,7 @@ static enum dc_status enable_link_dp(
if (link_settings.link_rate == LINK_RATE_LOW)
skip_video_pattern = false;
if (perform_link_training_with_retries(
link,
&link_settings,
......@@ -2739,7 +2744,6 @@ void core_link_enable_stream(
if (dc_is_dp_signal(pipe_ctx->stream->signal))
enable_stream_features(pipe_ctx);
}
}
void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option)
......
......@@ -4,6 +4,9 @@
#include "dc_link_dp.h"
#include "dm_helpers.h"
#include "opp.h"
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
#include "resource.h"
#endif
#include "inc/core_types.h"
#include "link_hwss.h"
......@@ -2547,6 +2550,7 @@ static bool retrieve_link_cap(struct dc_link *link)
dp_hw_fw_revision.ieee_fw_rev,
sizeof(dp_hw_fw_revision.ieee_fw_rev));
/* Connectivity log: detection */
CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
......@@ -2674,6 +2678,14 @@ static void set_crtc_test_pattern(struct dc_link *link,
stream->timing.display_color_depth;
struct bit_depth_reduction_params params;
struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
int width = pipe_ctx->stream->timing.h_addressable +
pipe_ctx->stream->timing.h_border_left +
pipe_ctx->stream->timing.h_border_right;
int height = pipe_ctx->stream->timing.v_addressable +
pipe_ctx->stream->timing.v_border_bottom +
pipe_ctx->stream->timing.v_border_top;
#endif
memset(&params, 0, sizeof(params));
......@@ -2717,6 +2729,30 @@ static void set_crtc_test_pattern(struct dc_link *link,
if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
controller_test_pattern, color_depth);
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
else if (opp->funcs->opp_set_disp_pattern_generator) {
struct pipe_ctx *bot_odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
if (bot_odm_pipe) {
struct output_pixel_processor *bot_opp = bot_odm_pipe->stream_res.opp;
bot_opp->funcs->opp_program_bit_depth_reduction(bot_opp, &params);
width /= 2;
bot_opp->funcs->opp_set_disp_pattern_generator(bot_opp,
controller_test_pattern,
color_depth,
NULL,
width,
height);
}
opp->funcs->opp_set_disp_pattern_generator(opp,
controller_test_pattern,
color_depth,
NULL,
width,
height);
}
#endif
}
break;
case DP_TEST_PATTERN_VIDEO_MODE:
......@@ -2729,6 +2765,30 @@ static void set_crtc_test_pattern(struct dc_link *link,
pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
color_depth);
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
else if (opp->funcs->opp_set_disp_pattern_generator) {
struct pipe_ctx *bot_odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
if (bot_odm_pipe) {
struct output_pixel_processor *bot_opp = bot_odm_pipe->stream_res.opp;
bot_opp->funcs->opp_program_bit_depth_reduction(bot_opp, &params);
width /= 2;
bot_opp->funcs->opp_set_disp_pattern_generator(bot_opp,
CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
color_depth,
NULL,
width,
height);
}
opp->funcs->opp_set_disp_pattern_generator(opp,
CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
color_depth,
NULL,
width,
height);
}
#endif
}
break;
......@@ -2903,3 +2963,5 @@ void dp_enable_mst_on_sink(struct dc_link *link, bool enable)
core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
}
......@@ -105,6 +105,7 @@ static void construct(struct dc_stream_state *stream,
/* EDID CAP translation for HDMI 2.0 */
stream->timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble;
update_stream_signal(stream, dc_sink_data);
stream->out_transfer_func = dc_create_transfer_func();
......@@ -355,6 +356,119 @@ bool dc_stream_set_cursor_position(
return true;
}
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
bool dc_stream_add_writeback(struct dc *dc,
struct dc_stream_state *stream,
struct dc_writeback_info *wb_info)
{
bool isDrc = false;
int i = 0;
if (stream == NULL) {
dm_error("DC: dc_stream is NULL!\n");
return false;
}
if (wb_info == NULL) {
dm_error("DC: dc_writeback_info is NULL!\n");
return false;
}
if (wb_info->dwb_pipe_inst >= MAX_DWB_PIPES) {
dm_error("DC: writeback pipe is invalid!\n");
return false;
}
wb_info->dwb_params.out_transfer_func = stream->out_transfer_func;
/* recalculate and apply DML parameters */
for (i = 0; i < stream->num_wb_info; i++) {
/*dynamic update*/
if (stream->writeback_info[i].wb_enabled &&
stream->writeback_info[i].dwb_pipe_inst == wb_info->dwb_pipe_inst) {
stream->writeback_info[i] = *wb_info;
isDrc = true;
}
}
if (!isDrc) {
stream->writeback_info[stream->num_wb_info++] = *wb_info;
}
if (!dc->hwss.update_bandwidth(dc, dc->current_state)) {
dm_error("DC: update_bandwidth failed!\n");
return false;
}
/* enable writeback */
if (dc->hwss.enable_writeback) {
struct dc_stream_status *stream_status = dc_stream_get_status(stream);
struct dwbc *dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
if (dwb->funcs->is_enabled(dwb)) {
/* writeback pipe already enabled, only need to update */
dc->hwss.update_writeback(dc, stream_status, wb_info);
} else {
/* Enable writeback pipe from scratch*/
dc->hwss.enable_writeback(dc, stream_status, wb_info);
}
}
return true;
}
bool dc_stream_remove_writeback(struct dc *dc,
struct dc_stream_state *stream,
uint32_t dwb_pipe_inst)
{
int i = 0, j = 0;
if (stream == NULL) {
dm_error("DC: dc_stream is NULL!\n");
return false;
}
if (dwb_pipe_inst >= MAX_DWB_PIPES) {
dm_error("DC: writeback pipe is invalid!\n");
return false;
}
// stream->writeback_info[dwb_pipe_inst].wb_enabled = false;
for (i = 0; i < stream->num_wb_info; i++) {
/*dynamic update*/
if (stream->writeback_info[i].wb_enabled &&
stream->writeback_info[i].dwb_pipe_inst == dwb_pipe_inst) {
stream->writeback_info[i].wb_enabled = false;
}
}
/* remove writeback info for disabled writeback pipes from stream */
for (i = 0, j = 0; i < stream->num_wb_info; i++) {
if (stream->writeback_info[i].wb_enabled) {
if (i != j)
/* trim the array */
stream->writeback_info[j] = stream->writeback_info[i];
j++;
}
}
stream->num_wb_info = j;
/* recalculate and apply DML parameters */
if (!dc->hwss.update_bandwidth(dc, dc->current_state)) {
dm_error("DC: update_bandwidth failed!\n");
return false;
}
/* disable writeback */
if (dc->hwss.disable_writeback)
dc->hwss.disable_writeback(dc, dwb_pipe_inst);
return true;
}
#endif
uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream)
{
uint8_t i;
......@@ -439,6 +553,77 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
return ret;
}
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
bool dc_stream_dmdata_status_done(struct dc *dc, struct dc_stream_state *stream)
{
bool status = true;
struct pipe_ctx *pipe = NULL;
int i;
if (!dc->hwss.dmdata_status_done)
return false;
for (i = 0; i < MAX_PIPES; i++) {
pipe = &dc->current_state->res_ctx.pipe_ctx[i];
if (pipe->stream == stream)
break;
}
/* Stream not found, by default we'll assume HUBP fetched dm data */
if (i == MAX_PIPES)
return true;
status = dc->hwss.dmdata_status_done(pipe);
return status;
}
bool dc_stream_set_dynamic_metadata(struct dc *dc,
struct dc_stream_state *stream,
struct dc_dmdata_attributes *attr)
{
struct pipe_ctx *pipe_ctx = NULL;
struct hubp *hubp;
int i;
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx->stream == stream)
break;
}
if (i == MAX_PIPES)
return false;
hubp = pipe_ctx->plane_res.hubp;
if (hubp == NULL)
return false;
pipe_ctx->stream->dmdata_address = attr->address;
if (pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata != NULL) {
if (pipe_ctx->stream->dmdata_address.quad_part != 0) {
/* if using dynamic meta, don't set up generic infopackets */
pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false;
pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata(
pipe_ctx->stream_res.stream_enc,
true, pipe_ctx->plane_res.hubp->inst,
dc_is_dp_signal(pipe_ctx->stream->signal) ?
dmdata_dp : dmdata_hdmi);
} else
pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata(
pipe_ctx->stream_res.stream_enc,
false, pipe_ctx->plane_res.hubp->inst,
dc_is_dp_signal(pipe_ctx->stream->signal) ?
dmdata_dp : dmdata_hdmi);
}
if (hubp->funcs->dmdata_set_attributes != NULL &&
pipe_ctx->stream->dmdata_address.quad_part != 0) {
hubp->funcs->dmdata_set_attributes(hubp, attr);
}
return true;
}
#endif
void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream)
{
......
......@@ -48,6 +48,20 @@ static void construct(struct dc_context *ctx, struct dc_plane_state *plane_state
plane_state->in_transfer_func->type = TF_TYPE_BYPASS;
plane_state->in_transfer_func->ctx = ctx;
}
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
plane_state->in_shaper_func = dc_create_transfer_func();
if (plane_state->in_shaper_func != NULL) {
plane_state->in_shaper_func->type = TF_TYPE_BYPASS;
plane_state->in_shaper_func->ctx = ctx;
}
plane_state->lut3d_func = dc_create_3dlut_func();
if (plane_state->lut3d_func != NULL) {
plane_state->lut3d_func->ctx = ctx;
plane_state->lut3d_func->initialized = false;
}
#endif
}
static void destruct(struct dc_plane_state *plane_state)
......@@ -60,6 +74,19 @@ static void destruct(struct dc_plane_state *plane_state)
plane_state->in_transfer_func);
plane_state->in_transfer_func = NULL;
}
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
if (plane_state->in_shaper_func != NULL) {
dc_transfer_func_release(
plane_state->in_shaper_func);
plane_state->in_shaper_func = NULL;
}
if (plane_state->lut3d_func != NULL) {
dc_3dlut_func_release(
plane_state->lut3d_func);
plane_state->lut3d_func = NULL;
}
#endif
}
/*******************************************************************************
......@@ -224,4 +251,40 @@ struct dc_transfer_func *dc_create_transfer_func(void)
return NULL;
}
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
static void dc_3dlut_func_free(struct kref *kref)
{
struct dc_3dlut *lut = container_of(kref, struct dc_3dlut, refcount);
kvfree(lut);
}
struct dc_3dlut *dc_create_3dlut_func(void)
{
struct dc_3dlut *lut = kvzalloc(sizeof(*lut), GFP_KERNEL);
if (lut == NULL)
goto alloc_fail;
kref_init(&lut->refcount);
lut->initialized = false;
return lut;
alloc_fail:
return NULL;
}
void dc_3dlut_func_release(struct dc_3dlut *lut)
{
kref_put(&lut->refcount, dc_3dlut_func_free);
}
void dc_3dlut_func_retain(struct dc_3dlut *lut)
{
kref_get(&lut->refcount);
}
#endif
......@@ -109,9 +109,19 @@ struct dc_caps {
bool force_dp_tps4_for_cp2520;
bool disable_dp_clk_share;
bool psp_setup_panel_mode;
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
bool hw_3d_lut;
#endif
struct dc_plane_cap planes[MAX_PLANES];
};
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
struct dc_bug_wa {
bool no_connect_phy_config;
bool dedcn20_305_wa;
};
#endif
struct dc_dcc_surface_param {
struct dc_size surface_size;
enum surface_pixel_format format;
......@@ -361,6 +371,41 @@ struct dc_debug_data {
uint32_t auxErrorCount;
};
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
struct dc_phy_addr_space_config {
struct {
uint64_t start_addr;
uint64_t end_addr;
uint64_t fb_top;
uint64_t fb_offset;
uint64_t fb_base;
uint64_t agp_top;
uint64_t agp_bot;
uint64_t agp_base;
} system_aperture;
struct {
uint64_t page_table_start_addr;
uint64_t page_table_end_addr;
uint64_t page_table_base_addr;
} gart_config;
};
struct dc_virtual_addr_space_config {
uint64_t page_table_start_addr;
uint64_t page_table_end_addr;
uint32_t page_table_block_size_in_bytes;
uint8_t page_table_depth; // 1 = 1 level, 2 = 2 level, etc. 0 = invalid
};
struct dc_addr_space_config {
struct dc_phy_addr_space_config pa_config;
struct dc_virtual_addr_space_config va_config;
uint32_t valid:1;
};
#endif
struct dc_bounding_box_overrides {
int sr_exit_time_ns;
int sr_enter_plus_exit_time_ns;
......@@ -381,7 +426,13 @@ struct dc {
struct dc_config config;
struct dc_debug_options debug;
struct dc_bounding_box_overrides bb_overrides;
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
struct dc_bug_wa work_arounds;
#endif
struct dc_context *ctx;
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
struct dc_addr_space_config vm_config;
#endif
uint8_t link_count;
struct dc_link *links[MAX_PIPES * 2];
......@@ -419,6 +470,10 @@ struct dc {
struct dc_debug_data debug_data;
const char *build_id;
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
struct vm_helper *vm_helper;
const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box;
#endif
};
enum frame_buffer_mode {
......@@ -452,7 +507,6 @@ struct dc_init_data {
struct dc_config flags;
uint32_t log_mask;
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
/**
* gpu_info FW provided soc bounding box struct or 0 if not
......@@ -467,6 +521,9 @@ struct dc_callback_init {
};
struct dc *dc_create(const struct dc_init_data *init_params);
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
bool dc_init_memory_hub(struct dc *dc, struct dc_addr_space_config *config);
#endif
void dc_init_callbacks(struct dc *dc,
const struct dc_callback_init *init_params);
void dc_destroy(struct dc **dc);
......@@ -538,6 +595,17 @@ struct dc_transfer_func {
};
};
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
struct dc_3dlut {
struct kref refcount;
struct tetrahedral_params lut_3d;
uint32_t hdr_multiplier;
bool initialized;
struct dc_context *ctx;
};
#endif
/*
* This structure is filled in by dc_surface_get_status and contains
* the last requested address and the currently active address so the called
......@@ -588,6 +656,9 @@ union surface_update_flags {
struct dc_plane_state {
struct dc_plane_address address;
struct dc_plane_flip_time time;
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
bool triplebuffer_flips;
#endif
struct scaling_taps scaling_quality;
struct rect src_rect;
struct rect dst_rect;
......@@ -610,6 +681,12 @@ struct dc_plane_state {
enum dc_color_space color_space;
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
struct dc_3dlut *lut3d_func;
struct dc_transfer_func *in_shaper_func;
struct dc_transfer_func *blend_tf;
#endif
enum surface_pixel_format format;
enum dc_rotation_angle rotation;
enum plane_stereo_format stereo_format;
......@@ -675,6 +752,10 @@ struct dc_surface_update {
const struct dc_csc_transform *input_csc_color_matrix;
const struct fixed31_32 *coeff_reduction_factor;
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
const struct dc_transfer_func *func_shaper;
const struct dc_3dlut *lut3d_func;
#endif
};
/*
......@@ -695,6 +776,11 @@ void dc_transfer_func_retain(struct dc_transfer_func *dc_tf);
void dc_transfer_func_release(struct dc_transfer_func *dc_tf);
struct dc_transfer_func *dc_create_transfer_func(void);
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
struct dc_3dlut *dc_create_3dlut_func(void);
void dc_3dlut_func_release(struct dc_3dlut *lut);
void dc_3dlut_func_retain(struct dc_3dlut *lut);
#endif
/*
* This structure holds a surface address. There could be multiple addresses
* in cases such as Stereo 3D, Planar YUV, etc. Other per-flip attributes such
......@@ -842,6 +928,7 @@ struct dc_sink {
struct stereo_3d_features features_3d[TIMING_3D_FORMAT_MAX];
bool converter_disable_audio;
/* private to DC core */
struct dc_link *link;
struct dc_context *ctx;
......
......@@ -51,6 +51,52 @@ struct freesync_context {
bool dummy;
};
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
enum hubp_dmdata_mode {
DMDATA_SW_MODE,
DMDATA_HW_MODE
};
struct dc_dmdata_attributes {
/* Specifies whether dynamic meta data will be updated by software
* or has to be fetched by hardware (DMA mode)
*/
enum hubp_dmdata_mode dmdata_mode;
/* Specifies if current dynamic meta data is to be used only for the current frame */
bool dmdata_repeat;
/* Specifies the size of Dynamic Metadata surface in byte. Size of 0 means no Dynamic metadata is fetched */
uint32_t dmdata_size;
/* Specifies if a new dynamic meta data should be fetched for an upcoming frame */
bool dmdata_updated;
/* If hardware mode is used, the base address where DMDATA surface is located */
PHYSICAL_ADDRESS_LOC address;
/* Specifies whether QOS level will be provided by TTU or it will come from DMDATA_QOS_LEVEL */
bool dmdata_qos_mode;
/* If qos_mode = 1, this is the QOS value to be used: */
uint32_t dmdata_qos_level;
/* Specifies the value in unit of REFCLK cycles to be added to the
* current time to produce the Amortized deadline for Dynamic Metadata chunk request
*/
uint32_t dmdata_dl_delta;
/* An unbounded array of uint32s, represents software dmdata to be loaded */
uint32_t *dmdata_sw_data;
};
#endif
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
struct dc_writeback_info {
bool wb_enabled;
int dwb_pipe_inst;
struct dc_dwb_params dwb_params;
struct mcif_buf_params mcif_buf_params;
};
struct dc_writeback_update {
unsigned int num_wb_info;
struct dc_writeback_info writeback_info[MAX_DWB_PIPES];
};
#endif
enum vertical_interrupt_ref_point {
START_V_UPDATE = 0,
START_V_SYNC,
......@@ -142,6 +188,11 @@ struct dc_stream_state {
struct crtc_trigger_info triggered_crtc_reset;
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
/* writeback */
unsigned int num_wb_info;
struct dc_writeback_info writeback_info[MAX_DWB_PIPES];
#endif
/* Computed state bits */
bool mode_changed : 1;
......@@ -184,6 +235,9 @@ struct dc_stream_update {
struct dc_csc_transform *output_csc_transform;
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
struct dc_writeback_update *wb_update;
#endif
};
bool dc_is_stream_unchanged(
......@@ -273,6 +327,19 @@ bool dc_add_all_planes_for_stream(
int plane_count,
struct dc_state *context);
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
bool dc_stream_add_writeback(struct dc *dc,
struct dc_stream_state *stream,
struct dc_writeback_info *wb_info);
bool dc_stream_remove_writeback(struct dc *dc,
struct dc_stream_state *stream,
uint32_t dwb_pipe_inst);
bool dc_stream_dmdata_status_done(struct dc *dc, struct dc_stream_state *stream);
bool dc_stream_set_dynamic_metadata(struct dc *dc,
struct dc_stream_state *stream,
struct dc_dmdata_attributes *dmdata_attr);
#endif
enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream);
/*
......
......@@ -41,6 +41,9 @@ enum pp_smu_ver {
*/
PP_SMU_UNSUPPORTED,
PP_SMU_VER_RV,
#ifndef CONFIG_TRIM_DRM_AMD_DC_DCN2_0
PP_SMU_VER_NV,
#endif
PP_SMU_VER_MAX
};
......@@ -64,7 +67,6 @@ enum pp_smu_status {
PP_SMU_RESULT_UNSUPPORTED
};
#define PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN 0x0
#define PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX 0xFFFF
......@@ -138,10 +140,119 @@ struct pp_smu_funcs_rv {
void (*set_pme_wa_enable)(struct pp_smu *pp);
};
#ifndef CONFIG_TRIM_DRM_AMD_DC_DCN2_0
/* Used by pp_smu_funcs_nv.set_voltage_by_freq
*
*/
enum pp_smu_nv_clock_id {
PP_SMU_NV_DISPCLK,
PP_SMU_NV_PHYCLK,
PP_SMU_NV_PIXELCLK
};
/*
* Used by pp_smu_funcs_nv.get_maximum_sustainable_clocks
*/
struct pp_smu_nv_clock_table {
// voltage managed SMU, freq set by driver
unsigned int displayClockInKhz;
unsigned int dppClockInKhz;
unsigned int phyClockInKhz;
unsigned int pixelClockInKhz;
unsigned int dscClockInKhz;
// freq/voltage managed by SMU
unsigned int fabricClockInKhz;
unsigned int socClockInKhz;
unsigned int dcfClockInKhz;
unsigned int uClockInKhz;
};
struct pp_smu_funcs_nv {
struct pp_smu pp_smu;
/* PPSMC_MSG_SetDisplayCount
* 0 triggers S0i2 optimization
*/
enum pp_smu_status (*set_display_count)(struct pp_smu *pp, int count);
/* PPSMC_MSG_SetHardMinDcfclkByFreq
* fixed clock at requested freq, either from FCH bypass or DFS
*/
enum pp_smu_status (*set_hard_min_dcfclk_by_freq)(struct pp_smu *pp, int Mhz);
/* PPSMC_MSG_SetMinDeepSleepDcfclk
* when DF is in cstate, dcf clock is further divided down
* to just above given frequency
*/
enum pp_smu_status (*set_min_deep_sleep_dcfclk)(struct pp_smu *pp, int Mhz);
/* PPSMC_MSG_SetHardMinUclkByFreq
* UCLK will vary with DPM, but never below requested hard min
*/
enum pp_smu_status (*set_hard_min_uclk_by_freq)(struct pp_smu *pp, int Mhz);
/* PPSMC_MSG_SetHardMinSocclkByFreq
* Needed for DWB support
*/
enum pp_smu_status (*set_hard_min_socclk_by_freq)(struct pp_smu *pp, int Mhz);
/* PME w/a */
enum pp_smu_status (*set_pme_wa_enable)(struct pp_smu *pp);
/* PPSMC_MSG_SetHardMinByFreq
* Needed to set ASIC voltages for clocks programmed by DAL
*/
enum pp_smu_status (*set_voltage_by_freq)(struct pp_smu *pp,
enum pp_smu_nv_clock_id clock_id, int Mhz);
/* reader and writer WM's are sent together as part of one table*/
/*
* PPSMC_MSG_SetDriverDramAddrHigh
* PPSMC_MSG_SetDriverDramAddrLow
* PPSMC_MSG_TransferTableDram2Smu
*
* on DCN20:
* reader fill clk = uclk
* reader drain clk = dcfclk
* writer fill clk = socclk
* writer drain clk = uclk
* */
enum pp_smu_status (*set_wm_ranges)(struct pp_smu *pp,
struct pp_smu_wm_range_sets *ranges);
/* Not a single SMU message. This call should return maximum sustainable limit for all
* clocks that DC depends on. These will be used as basis for mode enumeration.
*/
enum pp_smu_status (*get_maximum_sustainable_clocks)(struct pp_smu *pp,
struct pp_smu_nv_clock_table *max_clocks);
/* This call should return the discrete uclk DPM states available
*/
enum pp_smu_status (*get_uclk_dpm_states)(struct pp_smu *pp,
unsigned int *clock_values_in_khz, unsigned int *num_states);
/* Not a single SMU message. This call informs PPLIB that display will not be able
* to perform pstate handshaking in its current state. Typically this handshake
* is used to perform uCLK switching, so disabling pstate disables uCLK switching.
*
* Note that when setting handshake to unsupported, the call is pre-emptive. That means
* DC will make the call BEFORE setting up the display state which would cause pstate
* request to go un-acked. Only when the call completes should such a state be applied to
* DC hardware
*/
enum pp_smu_status (*set_pstate_handshake_support)(struct pp_smu *pp,
BOOLEAN pstate_handshake_supported);
};
#endif
struct pp_smu_funcs {
struct pp_smu ctx;
union {
struct pp_smu_funcs_rv rv_funcs;
#ifndef CONFIG_TRIM_DRM_AMD_DC_DCN2_0
struct pp_smu_funcs_nv nv_funcs;
#endif
};
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment