drm/amd/display: Add DSC support for Navi (v2)
Add support for DCN2 DSC (Display Stream Compression) HW Blocks: +--------++------+ +----------+ | HUBBUB || HUBP | <-- | MMHUBBUB | +--------++------+ +----------+ | ^ v | +--------+ +--------+ | DPP | | DWB | +--------+ +--------+ | v ^ +--------+ | | MPC | | +--------+ | | | v | +-------+ +-------+ | | OPP | <--> | DSC | | +-------+ +-------+ | | | v | +--------+ / | OPTC | -------------- +--------+ | v +--------+ +--------+ | DIO | | DCCG | +--------+ +--------+ v2: rebase (Alex) Signed-off-by: Harry Wentland <harry.wentland@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
b4f199c7b0
commit
97bda0322b
@ -25,6 +25,16 @@ config DRM_AMD_DC_DCN2_0
|
||||
Choose this option if you want to have
|
||||
Navi support for display engine
|
||||
|
||||
config DRM_AMD_DC_DSC_SUPPORT
|
||||
bool "DSC support"
|
||||
default n
|
||||
depends on DRM_AMD_DC && X86
|
||||
depends on DRM_AMD_DC_DCN1_0
|
||||
depends on DRM_AMD_DC_DCN2_0
|
||||
help
|
||||
Choose this option if you want to have
|
||||
Dynamic Stream Compression support
|
||||
|
||||
config DEBUG_KERNEL_DC
|
||||
bool "Enable kgdb break in DC"
|
||||
depends on DRM_AMD_DC
|
||||
|
@ -542,6 +542,16 @@ bool dm_helpers_submit_i2c(
|
||||
|
||||
return result;
|
||||
}
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
bool dm_helpers_dp_write_dsc_enable(
|
||||
struct dc_context *ctx,
|
||||
const struct dc_stream_state *stream,
|
||||
bool enable
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool dm_helpers_is_dp_sink_present(struct dc_link *link)
|
||||
{
|
||||
|
@ -30,6 +30,9 @@ DC_LIBS += dcn20
|
||||
endif
|
||||
|
||||
|
||||
ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
DC_LIBS += dsc
|
||||
endif
|
||||
|
||||
ifdef CONFIG_DRM_AMD_DC_DCN1_0
|
||||
DC_LIBS += dcn10 dml
|
||||
|
@ -56,6 +56,10 @@
|
||||
|
||||
#include "dc_link_dp.h"
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
#include "dsc.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
|
||||
#include "vm_helper.h"
|
||||
#endif
|
||||
@ -1730,6 +1734,23 @@ static void commit_planes_do_stream_update(struct dc *dc,
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DSC_SUPPORT)
|
||||
if (stream_update->dsc_config && dc->hwss.pipe_control_lock_global) {
|
||||
if (stream_update->dsc_config->num_slices_h &&
|
||||
stream_update->dsc_config->num_slices_v) {
|
||||
/* dsc enable */
|
||||
dc->hwss.pipe_control_lock_global(dc, pipe_ctx, true);
|
||||
dp_set_dsc_enable(pipe_ctx, true);
|
||||
dc->hwss.pipe_control_lock_global(dc, pipe_ctx, false);
|
||||
} else {
|
||||
/* dsc disable */
|
||||
dc->hwss.pipe_control_lock_global(dc, pipe_ctx, true);
|
||||
dp_set_dsc_enable(pipe_ctx, false);
|
||||
dc->hwss.pipe_control_lock_global(dc, pipe_ctx, false);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
/* Full fe update*/
|
||||
if (update_type == UPDATE_TYPE_FAST)
|
||||
continue;
|
||||
|
@ -1508,6 +1508,9 @@ static enum dc_status enable_link_dp(
|
||||
if (link_settings.link_rate == LINK_RATE_LOW)
|
||||
skip_video_pattern = false;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
dp_set_fec_ready(link, true);
|
||||
#endif
|
||||
|
||||
if (perform_link_training_with_retries(
|
||||
link,
|
||||
@ -1520,6 +1523,9 @@ static enum dc_status enable_link_dp(
|
||||
else
|
||||
status = DC_FAIL_DP_LINK_TRAINING;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
dp_set_fec_enable(link, true);
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -2142,6 +2148,14 @@ static void disable_link(struct dc_link *link, enum signal_type signal)
|
||||
dp_disable_link_phy(link, signal);
|
||||
else
|
||||
dp_disable_link_phy_mst(link, signal);
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
|
||||
if (dc_is_dp_sst_signal(signal) ||
|
||||
link->mst_stream_alloc_table.stream_count == 0) {
|
||||
dp_set_fec_enable(link, false);
|
||||
dp_set_fec_ready(link, false);
|
||||
}
|
||||
#endif
|
||||
} else
|
||||
link->link_enc->funcs->disable_output(link->link_enc, signal);
|
||||
|
||||
@ -2376,6 +2390,11 @@ static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream)
|
||||
&stream->link->cur_link_settings);
|
||||
link_rate_in_mbytes_per_sec /= 8000; /* Kbits to MBytes */
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
if (stream->link->fec_state != dc_link_fec_not_ready)
|
||||
link_rate_in_mbytes_per_sec = (link_rate_in_mbytes_per_sec * 970)/1000;
|
||||
#endif
|
||||
|
||||
mbytes_per_sec = dc_fixpt_from_int(link_rate_in_mbytes_per_sec);
|
||||
|
||||
return dc_fixpt_div_int(mbytes_per_sec, 54);
|
||||
@ -2738,12 +2757,30 @@ void core_link_enable_stream(
|
||||
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
|
||||
allocate_mst_payload(pipe_ctx);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
if (pipe_ctx->stream->timing.flags.DSC &&
|
||||
(dc_is_dp_signal(pipe_ctx->stream->signal) ||
|
||||
dc_is_virtual_signal(pipe_ctx->stream->signal))) {
|
||||
dp_set_dsc_enable(pipe_ctx, true);
|
||||
pipe_ctx->stream_res.tg->funcs->wait_for_state(
|
||||
pipe_ctx->stream_res.tg,
|
||||
CRTC_STATE_VBLANK);
|
||||
}
|
||||
#endif
|
||||
core_dc->hwss.unblank_stream(pipe_ctx,
|
||||
&pipe_ctx->stream->link->cur_link_settings);
|
||||
|
||||
if (dc_is_dp_signal(pipe_ctx->stream->signal))
|
||||
enable_stream_features(pipe_ctx);
|
||||
}
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
else { // if (IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment))
|
||||
if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
|
||||
dc_is_virtual_signal(pipe_ctx->stream->signal))
|
||||
dp_set_dsc_enable(pipe_ctx, true);
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option)
|
||||
@ -2784,6 +2821,12 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option)
|
||||
core_dc->hwss.disable_stream(pipe_ctx, option);
|
||||
|
||||
disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal);
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
if (pipe_ctx->stream->timing.flags.DSC &&
|
||||
dc_is_dp_signal(pipe_ctx->stream->signal)) {
|
||||
dp_set_dsc_enable(pipe_ctx, false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
|
||||
@ -2851,6 +2894,14 @@ uint32_t dc_bandwidth_in_kbps_from_timing(
|
||||
uint32_t bits_per_channel = 0;
|
||||
uint32_t kbps;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
if (timing->flags.DSC) {
|
||||
kbps = (timing->pix_clk_100hz * timing->dsc_cfg.bits_per_pixel);
|
||||
kbps = kbps / 160 + ((kbps % 160) ? 1 : 0);
|
||||
return kbps;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (timing->display_color_depth) {
|
||||
case COLOR_DEPTH_666:
|
||||
bits_per_channel = 6;
|
||||
|
@ -4,6 +4,9 @@
|
||||
#include "dc_link_dp.h"
|
||||
#include "dm_helpers.h"
|
||||
#include "opp.h"
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
#include "dsc.h"
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
|
||||
#include "resource.h"
|
||||
#endif
|
||||
@ -2379,6 +2382,10 @@ static bool retrieve_link_cap(struct dc_link *link)
|
||||
uint32_t read_dpcd_retry_cnt = 3;
|
||||
int i;
|
||||
struct dp_sink_hw_fw_revision dp_hw_fw_revision;
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
uint8_t dsc_data[16];
|
||||
struct dsc_dec_dpcd_caps *dsc_caps;
|
||||
#endif
|
||||
|
||||
memset(dpcd_data, '\0', sizeof(dpcd_data));
|
||||
memset(&down_strm_port_count,
|
||||
@ -2550,6 +2557,90 @@ static bool retrieve_link_cap(struct dc_link *link)
|
||||
dp_hw_fw_revision.ieee_fw_rev,
|
||||
sizeof(dp_hw_fw_revision.ieee_fw_rev));
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
dsc_caps = &link->dpcd_caps.dsc_sink_caps;
|
||||
memset(dsc_caps, '\0', sizeof(*dsc_caps));
|
||||
memset(&link->dpcd_caps.dsc_sink_caps, '\0',
|
||||
sizeof(link->dpcd_caps.dsc_sink_caps));
|
||||
memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap));
|
||||
/* Read DSC and FEC sink capabilities if DP revision is 1.4 and up */
|
||||
if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14) {
|
||||
status = core_link_read_dpcd(
|
||||
link,
|
||||
DP_DSC_SUPPORT,
|
||||
dsc_data,
|
||||
sizeof(dsc_data));
|
||||
if (status == DC_OK) {
|
||||
DC_LOG_DSC("DSC capability read at link %d:",
|
||||
link->link_index);
|
||||
DC_LOG_DSC("\t%02x %02x %02x %02x",
|
||||
dsc_data[0], dsc_data[1],
|
||||
dsc_data[2], dsc_data[3]);
|
||||
DC_LOG_DSC("\t%02x %02x %02x %02x",
|
||||
dsc_data[4], dsc_data[5],
|
||||
dsc_data[6], dsc_data[7]);
|
||||
DC_LOG_DSC("\t%02x %02x %02x %02x",
|
||||
dsc_data[8], dsc_data[9],
|
||||
dsc_data[10], dsc_data[11]);
|
||||
DC_LOG_DSC("\t%02x %02x %02x %02x",
|
||||
dsc_data[12], dsc_data[13],
|
||||
dsc_data[14], dsc_data[15]);
|
||||
} else {
|
||||
dm_error("%s: Read DSC dpcd data failed.\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dc_dsc_parse_dsc_dpcd(dsc_data,
|
||||
dsc_caps)) {
|
||||
DC_LOG_DSC("DSC capability parsed at link %d:",
|
||||
link->link_index);
|
||||
DC_LOG_DSC("\tis_dsc_supported:\t%d",
|
||||
dsc_caps->is_dsc_supported);
|
||||
DC_LOG_DSC("\tdsc_version:\t%d", dsc_caps->dsc_version);
|
||||
DC_LOG_DSC("\trc_buffer_size:\t%d",
|
||||
dsc_caps->rc_buffer_size);
|
||||
DC_LOG_DSC("\tslice_caps1:\t0x%x20",
|
||||
dsc_caps->slice_caps1.raw);
|
||||
DC_LOG_DSC("\tslice_caps2:\t0x%x20",
|
||||
dsc_caps->slice_caps2.raw);
|
||||
DC_LOG_DSC("\tlb_bit_depth:\t%d",
|
||||
dsc_caps->lb_bit_depth);
|
||||
DC_LOG_DSC("\tis_block_pred_supported:\t%d",
|
||||
dsc_caps->is_block_pred_supported);
|
||||
DC_LOG_DSC("\tedp_max_bits_per_pixel:\t%d",
|
||||
dsc_caps->edp_max_bits_per_pixel);
|
||||
DC_LOG_DSC("\tcolor_formats:\t%d",
|
||||
dsc_caps->color_formats.raw);
|
||||
DC_LOG_DSC("\tcolor_depth:\t%d",
|
||||
dsc_caps->color_depth.raw);
|
||||
DC_LOG_DSC("\tthroughput_mode_0_mps:\t%d",
|
||||
dsc_caps->throughput_mode_0_mps);
|
||||
DC_LOG_DSC("\tthroughput_mode_1_mps:\t%d",
|
||||
dsc_caps->throughput_mode_1_mps);
|
||||
DC_LOG_DSC("\tmax_slice_width:\t%d",
|
||||
dsc_caps->max_slice_width);
|
||||
DC_LOG_DSC("\tbpp_increment_div:\t%d",
|
||||
dsc_caps->bpp_increment_div);
|
||||
} else {
|
||||
/* Some sinks return bogus DSC DPCD data
|
||||
* when they don't support DSC.
|
||||
*/
|
||||
dm_error("%s: DSC DPCD data doesn't make sense. "
|
||||
"DSC will be disabled.\n", __func__);
|
||||
memset(&link->dpcd_caps.dsc_sink_caps, '\0',
|
||||
sizeof(link->dpcd_caps.dsc_sink_caps));
|
||||
}
|
||||
|
||||
status = core_link_read_dpcd(
|
||||
link,
|
||||
DP_FEC_CAPABILITY,
|
||||
&link->dpcd_caps.fec_cap.raw,
|
||||
sizeof(link->dpcd_caps.fec_cap.raw));
|
||||
if (status != DC_OK)
|
||||
dm_error("%s: Read FEC dpcd register failed.\n",
|
||||
__func__);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Connectivity log: detection */
|
||||
CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
|
||||
@ -2964,4 +3055,66 @@ void dp_enable_mst_on_sink(struct dc_link *link, bool enable)
|
||||
core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
void dp_set_fec_ready(struct dc_link *link, bool ready)
|
||||
{
|
||||
/* FEC has to be "set ready" before the link training.
|
||||
* The policy is to always train with FEC
|
||||
* if the sink supports it and leave it enabled on link.
|
||||
* If FEC is not supported, disable it.
|
||||
*/
|
||||
struct link_encoder *link_enc = link->link_enc;
|
||||
uint8_t fec_config = 0;
|
||||
|
||||
if (link->dc->debug.disable_fec ||
|
||||
IS_FPGA_MAXIMUS_DC(link->ctx->dce_environment))
|
||||
return;
|
||||
|
||||
if (link_enc->funcs->fec_set_ready &&
|
||||
link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
|
||||
if (link->fec_state == dc_link_fec_not_ready && ready) {
|
||||
fec_config = 1;
|
||||
if (core_link_write_dpcd(link,
|
||||
DP_FEC_CONFIGURATION,
|
||||
&fec_config,
|
||||
sizeof(fec_config)) == DC_OK) {
|
||||
link_enc->funcs->fec_set_ready(link_enc, true);
|
||||
link->fec_state = dc_link_fec_ready;
|
||||
} else {
|
||||
dm_error("dpcd write failed to set fec_ready");
|
||||
}
|
||||
} else if (link->fec_state == dc_link_fec_ready && !ready) {
|
||||
fec_config = 0;
|
||||
core_link_write_dpcd(link,
|
||||
DP_FEC_CONFIGURATION,
|
||||
&fec_config,
|
||||
sizeof(fec_config));
|
||||
link->link_enc->funcs->fec_set_ready(
|
||||
link->link_enc, false);
|
||||
link->fec_state = dc_link_fec_not_ready;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dp_set_fec_enable(struct dc_link *link, bool enable)
|
||||
{
|
||||
struct link_encoder *link_enc = link->link_enc;
|
||||
|
||||
if (link->dc->debug.disable_fec ||
|
||||
IS_FPGA_MAXIMUS_DC(link->ctx->dce_environment))
|
||||
return;
|
||||
|
||||
if (link_enc->funcs->fec_set_enable &&
|
||||
link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
|
||||
if (link->fec_state == dc_link_fec_ready && enable) {
|
||||
msleep(1);
|
||||
link_enc->funcs->fec_set_enable(link_enc, true);
|
||||
link->fec_state = dc_link_fec_enabled;
|
||||
} else if (link->fec_state == dc_link_fec_enabled && !enable) {
|
||||
link_enc->funcs->fec_set_enable(link_enc, false);
|
||||
link->fec_state = dc_link_fec_ready;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -12,6 +12,12 @@
|
||||
#include "dc_link_ddc.h"
|
||||
#include "dm_helpers.h"
|
||||
#include "dpcd_defs.h"
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
#include "dsc.h"
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
|
||||
#include "resource.h"
|
||||
#endif
|
||||
|
||||
enum dc_status core_link_read_dpcd(
|
||||
struct dc_link *link,
|
||||
@ -360,3 +366,142 @@ void dp_retrain_link_dp_test(struct dc_link *link,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
#define DC_LOGGER \
|
||||
dsc->ctx->logger
|
||||
static void dsc_optc_config_log(struct display_stream_compressor *dsc,
|
||||
struct dsc_optc_config *config)
|
||||
{
|
||||
DC_LOG_DSC("Setting optc DSC config at DSC inst %d", dsc->inst);
|
||||
DC_LOG_DSC("\n\tbytes_per_pixel %d\n\tis_pixel_format_444 %d\n\tslice_width %d",
|
||||
config->bytes_per_pixel,
|
||||
config->is_pixel_format_444, config->slice_width);
|
||||
}
|
||||
|
||||
static bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
|
||||
{
|
||||
struct dc *core_dc = pipe_ctx->stream->ctx->dc;
|
||||
struct dc_stream_state *stream = pipe_ctx->stream;
|
||||
bool result = false;
|
||||
|
||||
if (IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment))
|
||||
result = true;
|
||||
else
|
||||
result = dm_helpers_dp_write_dsc_enable(core_dc->ctx, stream, enable);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* This has to be done after DSC was enabled on RX first, i.e. after dp_enable_dsc_on_rx() had been called
|
||||
*/
|
||||
static void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
|
||||
{
|
||||
struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
|
||||
struct dc *core_dc = pipe_ctx->stream->ctx->dc;
|
||||
struct dc_stream_state *stream = pipe_ctx->stream;
|
||||
struct pipe_ctx *odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
|
||||
|
||||
if (enable) {
|
||||
/* TODO proper function */
|
||||
struct dsc_config dsc_cfg;
|
||||
struct dsc_optc_config dsc_optc_cfg;
|
||||
enum optc_dsc_mode optc_dsc_mode;
|
||||
uint8_t dsc_packed_pps[128];
|
||||
|
||||
/* Enable DSC hw block */
|
||||
dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
|
||||
dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
|
||||
dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
|
||||
dsc_cfg.color_depth = stream->timing.display_color_depth;
|
||||
dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
|
||||
|
||||
dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg, &dsc_packed_pps[0]);
|
||||
if (odm_pipe) {
|
||||
struct display_stream_compressor *bot_dsc = odm_pipe->stream_res.dsc;
|
||||
uint8_t dsc_packed_pps_odm[128];
|
||||
|
||||
dsc_cfg.pic_width /= 2;
|
||||
ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % 2 == 0);
|
||||
dsc_cfg.dc_dsc_cfg.num_slices_h /= 2;
|
||||
dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg, &dsc_packed_pps_odm[0]);
|
||||
bot_dsc->funcs->dsc_set_config(bot_dsc, &dsc_cfg, &dsc_optc_cfg, &dsc_packed_pps_odm[0]);
|
||||
bot_dsc->funcs->dsc_enable(bot_dsc, odm_pipe->stream_res.opp->inst);
|
||||
}
|
||||
dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
|
||||
|
||||
optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
|
||||
|
||||
dsc_optc_config_log(dsc, &dsc_optc_cfg);
|
||||
/* Enable DSC in encoder */
|
||||
if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment) && pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config)
|
||||
pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
|
||||
optc_dsc_mode,
|
||||
dsc_optc_cfg.bytes_per_pixel,
|
||||
dsc_optc_cfg.slice_width,
|
||||
&dsc_packed_pps[0]);
|
||||
|
||||
/* Enable DSC in OPTC */
|
||||
pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,
|
||||
optc_dsc_mode,
|
||||
dsc_optc_cfg.bytes_per_pixel,
|
||||
dsc_optc_cfg.slice_width);
|
||||
} else {
|
||||
/* disable DSC in OPTC */
|
||||
pipe_ctx->stream_res.tg->funcs->set_dsc_config(
|
||||
pipe_ctx->stream_res.tg,
|
||||
OPTC_DSC_DISABLED, 0, 0);
|
||||
|
||||
/* disable DSC in stream encoder */
|
||||
if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
|
||||
pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
|
||||
pipe_ctx->stream_res.stream_enc,
|
||||
OPTC_DSC_DISABLED, 0, 0, NULL);
|
||||
}
|
||||
|
||||
/* disable DSC block */
|
||||
pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
|
||||
if (odm_pipe)
|
||||
odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
|
||||
}
|
||||
}
|
||||
|
||||
bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable)
|
||||
{
|
||||
struct dc_stream_state *stream = pipe_ctx->stream;
|
||||
struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
|
||||
bool result = false;
|
||||
|
||||
if (!dsc)
|
||||
goto out;
|
||||
|
||||
if (enable && stream->is_dsc_enabled) {
|
||||
/* update dsc stream */
|
||||
dp_set_dsc_on_stream(pipe_ctx, true);
|
||||
stream->is_dsc_enabled = true;
|
||||
result = true;
|
||||
} else if (enable && !stream->is_dsc_enabled) {
|
||||
/* enable dsc on non dsc stream */
|
||||
if (dp_set_dsc_on_rx(pipe_ctx, true)) {
|
||||
dp_set_dsc_on_stream(pipe_ctx, true);
|
||||
stream->is_dsc_enabled = true;
|
||||
result = true;
|
||||
} else {
|
||||
stream->is_dsc_enabled = false;
|
||||
result = false;
|
||||
}
|
||||
} else if (!enable && stream->is_dsc_enabled) {
|
||||
/* disable dsc on dsc stream */
|
||||
dp_set_dsc_on_rx(pipe_ctx, false);
|
||||
dp_set_dsc_on_stream(pipe_ctx, false);
|
||||
stream->is_dsc_enabled = false;
|
||||
result = true;
|
||||
} else {
|
||||
/* disable dsc on non dsc stream */
|
||||
result = true;
|
||||
}
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -105,6 +105,16 @@ 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;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
memset(&stream->timing.dsc_cfg, 0, sizeof(stream->timing.dsc_cfg));
|
||||
stream->timing.dsc_cfg.num_slices_h = 0;
|
||||
stream->timing.dsc_cfg.num_slices_v = 0;
|
||||
stream->timing.dsc_cfg.bits_per_pixel = 128;
|
||||
stream->timing.dsc_cfg.block_pred_enable = 1;
|
||||
stream->timing.dsc_cfg.linebuf_depth = 9;
|
||||
stream->timing.dsc_cfg.version_minor = 2;
|
||||
stream->timing.dsc_cfg.ycbcr422_simple = 0;
|
||||
#endif
|
||||
|
||||
update_stream_signal(stream, dc_sink_data);
|
||||
|
||||
|
@ -331,6 +331,9 @@ struct dc_debug_options {
|
||||
bool disable_dfs_bypass;
|
||||
bool disable_dpp_power_gate;
|
||||
bool disable_hubp_power_gate;
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
bool disable_dsc_power_gate;
|
||||
#endif
|
||||
bool disable_pplib_wm_range;
|
||||
enum wm_report_mode pplib_wm_report_mode;
|
||||
unsigned int min_disp_clk_khz;
|
||||
@ -363,6 +366,9 @@ struct dc_debug_options {
|
||||
unsigned int force_fclk_khz;
|
||||
bool disable_tri_buf;
|
||||
struct dc_bw_validation_profile bw_val_profile;
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
bool disable_fec;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct dc_debug_data {
|
||||
@ -894,6 +900,10 @@ struct dpcd_caps {
|
||||
bool panel_mode_edp;
|
||||
bool dpcd_display_control_capable;
|
||||
bool ext_receiver_cap_field_present;
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
union fec_capability fec_cap;
|
||||
struct dsc_dec_dpcd_caps dsc_sink_caps;
|
||||
#endif
|
||||
};
|
||||
|
||||
#include "dc_link.h"
|
||||
@ -928,6 +938,14 @@ struct dc_sink {
|
||||
struct stereo_3d_features features_3d[TIMING_3D_FORMAT_MAX];
|
||||
bool converter_disable_audio;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
struct dc_sink_dsc_caps {
|
||||
// 'true' if these are virtual DPCD's DSC caps (immediately upstream of sink in MST topology),
|
||||
// 'false' if they are sink's DSC caps
|
||||
bool is_virtual_dpcd_dsc;
|
||||
struct dsc_dec_dpcd_caps dsc_dec_caps;
|
||||
} sink_dsc_caps;
|
||||
#endif
|
||||
|
||||
/* private to DC core */
|
||||
struct dc_link *link;
|
||||
@ -986,4 +1004,10 @@ unsigned int dc_get_target_backlight_pwm(struct dc *dc);
|
||||
|
||||
bool dc_is_dmcu_initialized(struct dc *dc);
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DSC_SUPPORT)
|
||||
/*******************************************************************************
|
||||
* DSC Interfaces
|
||||
******************************************************************************/
|
||||
#include "dc_dsc.h"
|
||||
#endif
|
||||
#endif /* DC_INTERFACE_H_ */
|
||||
|
@ -512,4 +512,18 @@ union test_misc {
|
||||
unsigned char raw;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
/* FEC capability DPCD register field bits-*/
|
||||
union fec_capability {
|
||||
struct {
|
||||
uint8_t FEC_CAPABLE:1;
|
||||
uint8_t UNCORRECTED_BLOCK_ERROR_COUNT_CAPABLE:1;
|
||||
uint8_t CORRECTED_BLOCK_ERROR_COUNT_CAPABLE:1;
|
||||
uint8_t BIT_ERROR_COUNT_CAPABLE:1;
|
||||
uint8_t RESERVED:4;
|
||||
} bits;
|
||||
uint8_t raw;
|
||||
};
|
||||
#endif /* CONFIG_DRM_AMD_DC_DSC_SUPPORT */
|
||||
|
||||
#endif /* DC_DP_TYPES_H */
|
||||
|
61
drivers/gpu/drm/amd/display/dc/dc_dsc.h
Normal file
61
drivers/gpu/drm/amd/display/dc/dc_dsc.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
#ifndef DC_DSC_H_
|
||||
#define DC_DSC_H_
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
*
|
||||
* Author: AMD
|
||||
*/
|
||||
struct dc_dsc_bw_range {
|
||||
uint32_t min_kbps;
|
||||
uint32_t min_target_bpp_x16;
|
||||
uint32_t max_kbps;
|
||||
uint32_t max_target_bpp_x16;
|
||||
uint32_t stream_kbps;
|
||||
};
|
||||
|
||||
|
||||
bool dc_dsc_parse_dsc_dpcd(const uint8_t *dpcd_dsc_data,
|
||||
struct dsc_dec_dpcd_caps *dsc_sink_caps);
|
||||
|
||||
bool dc_dsc_compute_bandwidth_range(
|
||||
const struct dc *dc,
|
||||
const struct dsc_dec_dpcd_caps *dsc_sink_caps,
|
||||
const struct dc_crtc_timing *timing,
|
||||
struct dc_dsc_bw_range *range);
|
||||
bool dc_dsc_compute_config(
|
||||
const struct dc *dc,
|
||||
const struct dsc_dec_dpcd_caps *dsc_sink_caps,
|
||||
int target_bandwidth,
|
||||
const struct dc_crtc_timing *timing,
|
||||
struct dc_dsc_config *dsc_cfg);
|
||||
|
||||
bool dc_check_and_fit_timing_into_bandwidth_with_dsc_legacy(
|
||||
const struct dc *pDC,
|
||||
const struct dc_link *link,
|
||||
struct dc_crtc_timing *timing);
|
||||
|
||||
bool dc_setup_dsc_in_timing_legacy(const struct dc *pDC,
|
||||
const struct dsc_dec_dpcd_caps *dsc_sink_caps,
|
||||
int available_bandwidth_kbps,
|
||||
struct dc_crtc_timing *timing);
|
||||
#endif
|
||||
#endif
|
@ -709,6 +709,9 @@ struct dc_crtc_timing_flags {
|
||||
* rates less than or equal to 340Mcsc */
|
||||
uint32_t LTE_340MCSC_SCRAMBLE:1;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
uint32_t DSC : 1; /* Use DSC with this timing */
|
||||
#endif
|
||||
};
|
||||
|
||||
enum dc_timing_3d_format {
|
||||
@ -755,6 +758,18 @@ struct dc_crtc_timing_adjust {
|
||||
uint32_t v_total_max;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
struct dc_dsc_config {
|
||||
uint32_t num_slices_h; /* Number of DSC slices - horizontal */
|
||||
uint32_t num_slices_v; /* Number of DSC slices - vertical */
|
||||
uint32_t bits_per_pixel; /* DSC target bitrate in 1/16 of bpp (e.g. 128 -> 8bpp) */
|
||||
bool block_pred_enable; /* DSC block prediction enable */
|
||||
uint32_t linebuf_depth; /* DSC line buffer depth */
|
||||
uint32_t version_minor; /* DSC minor version. Full version is formed as 1.version_minor. */
|
||||
bool ycbcr422_simple; /* Tell DSC engine to convert YCbCr 4:2:2 to 'YCbCr 4:2:2 simple'. */
|
||||
int32_t rc_buffer_size; /* DSC RC buffer block size in bytes */
|
||||
};
|
||||
#endif
|
||||
struct dc_crtc_timing {
|
||||
uint32_t h_total;
|
||||
uint32_t h_border_left;
|
||||
@ -781,6 +796,9 @@ struct dc_crtc_timing {
|
||||
enum scanning_type scan_type;
|
||||
|
||||
struct dc_crtc_timing_flags flags;
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
struct dc_dsc_config dsc_cfg;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Passed on init */
|
||||
|
@ -29,6 +29,13 @@
|
||||
#include "dc_types.h"
|
||||
#include "grph_object_defs.h"
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
enum dc_link_fec_state {
|
||||
dc_link_fec_not_ready,
|
||||
dc_link_fec_ready,
|
||||
dc_link_fec_enabled
|
||||
};
|
||||
#endif
|
||||
struct dc_link_status {
|
||||
bool link_active;
|
||||
struct dpcd_caps *dpcd_caps;
|
||||
@ -129,6 +136,9 @@ struct dc_link {
|
||||
|
||||
struct link_trace link_trace;
|
||||
struct gpio *hpd_gpio;
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
enum dc_link_fec_state fec_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link);
|
||||
|
@ -211,6 +211,9 @@ struct dc_stream_state {
|
||||
bool apply_seamless_boot_optimization;
|
||||
|
||||
uint32_t stream_id;
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
bool is_dsc_enabled;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct dc_stream_update {
|
||||
@ -238,6 +241,9 @@ struct dc_stream_update {
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
|
||||
struct dc_writeback_update *wb_update;
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_AMD_DC_DSC_SUPPORT)
|
||||
struct dc_dsc_config *dsc_config;
|
||||
#endif
|
||||
};
|
||||
|
||||
bool dc_is_stream_unchanged(
|
||||
|
@ -553,6 +553,9 @@ enum dc_infoframe_type {
|
||||
DC_HDMI_INFOFRAME_TYPE_AVI = 0x82,
|
||||
DC_HDMI_INFOFRAME_TYPE_SPD = 0x83,
|
||||
DC_HDMI_INFOFRAME_TYPE_AUDIO = 0x84,
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
DC_DP_INFOFRAME_TYPE_PPS = 0x10,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct dc_info_packet {
|
||||
@ -706,4 +709,70 @@ struct AsicStateEx {
|
||||
unsigned int phyClock;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
/* DSC DPCD capabilities */
|
||||
union dsc_slice_caps1 {
|
||||
struct {
|
||||
uint8_t NUM_SLICES_1 : 1;
|
||||
uint8_t NUM_SLICES_2 : 1;
|
||||
uint8_t RESERVED : 1;
|
||||
uint8_t NUM_SLICES_4 : 1;
|
||||
uint8_t NUM_SLICES_6 : 1;
|
||||
uint8_t NUM_SLICES_8 : 1;
|
||||
uint8_t NUM_SLICES_10 : 1;
|
||||
uint8_t NUM_SLICES_12 : 1;
|
||||
} bits;
|
||||
uint8_t raw;
|
||||
};
|
||||
|
||||
union dsc_slice_caps2 {
|
||||
struct {
|
||||
uint8_t NUM_SLICES_16 : 1;
|
||||
uint8_t NUM_SLICES_20 : 1;
|
||||
uint8_t NUM_SLICES_24 : 1;
|
||||
uint8_t RESERVED : 5;
|
||||
} bits;
|
||||
uint8_t raw;
|
||||
};
|
||||
|
||||
union dsc_color_formats {
|
||||
struct {
|
||||
uint8_t RGB : 1;
|
||||
uint8_t YCBCR_444 : 1;
|
||||
uint8_t YCBCR_SIMPLE_422 : 1;
|
||||
uint8_t YCBCR_NATIVE_422 : 1;
|
||||
uint8_t YCBCR_NATIVE_420 : 1;
|
||||
uint8_t RESERVED : 3;
|
||||
} bits;
|
||||
uint8_t raw;
|
||||
};
|
||||
|
||||
union dsc_color_depth {
|
||||
struct {
|
||||
uint8_t RESERVED1 : 1;
|
||||
uint8_t COLOR_DEPTH_8_BPC : 1;
|
||||
uint8_t COLOR_DEPTH_10_BPC : 1;
|
||||
uint8_t COLOR_DEPTH_12_BPC : 1;
|
||||
uint8_t RESERVED2 : 3;
|
||||
} bits;
|
||||
uint8_t raw;
|
||||
};
|
||||
|
||||
struct dsc_dec_dpcd_caps {
|
||||
bool is_dsc_supported;
|
||||
uint8_t dsc_version;
|
||||
int32_t rc_buffer_size; /* DSC RC buffer block size in bytes */
|
||||
union dsc_slice_caps1 slice_caps1;
|
||||
union dsc_slice_caps2 slice_caps2;
|
||||
int32_t lb_bit_depth;
|
||||
bool is_block_pred_supported;
|
||||
int32_t edp_max_bits_per_pixel; /* Valid only in eDP */
|
||||
union dsc_color_formats color_formats;
|
||||
union dsc_color_depth color_depth;
|
||||
int32_t throughput_mode_0_mps; /* In MPs */
|
||||
int32_t throughput_mode_1_mps; /* In MPs */
|
||||
int32_t max_slice_width;
|
||||
uint32_t bpp_increment_div; /* bpp increment divisor, e.g. if 16, it's 1/16th of a bit */
|
||||
};
|
||||
#endif
|
||||
#endif /* DC_TYPES_H_ */
|
||||
|
@ -49,6 +49,9 @@
|
||||
#include "clk_mgr.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
#include "dsc.h"
|
||||
#endif
|
||||
|
||||
#define DC_LOGGER_INIT(logger)
|
||||
|
||||
@ -347,6 +350,61 @@ void dcn10_log_hw_state(struct dc *dc,
|
||||
}
|
||||
DTN_INFO("\n");
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
DTN_INFO("DSC: CLOCK_EN SLICE_WIDTH Bytes_pp\n");
|
||||
for (i = 0; i < pool->res_cap->num_dsc; i++) {
|
||||
struct display_stream_compressor *dsc = pool->dscs[i];
|
||||
struct dcn_dsc_state s = {0};
|
||||
|
||||
dsc->funcs->dsc_read_state(dsc, &s);
|
||||
DTN_INFO("[%d]: %-9d %-12d %-10d\n",
|
||||
dsc->inst,
|
||||
s.dsc_clock_en,
|
||||
s.dsc_slice_width,
|
||||
s.dsc_bytes_per_pixel);
|
||||
DTN_INFO("\n");
|
||||
}
|
||||
DTN_INFO("\n");
|
||||
|
||||
DTN_INFO("S_ENC: DSC_MODE SEC_GSP7_LINE_NUM"
|
||||
" VBID6_LINE_REFERENCE VBID6_LINE_NUM SEC_GSP7_ENABLE SEC_STREAM_ENABLE\n");
|
||||
for (i = 0; i < pool->stream_enc_count; i++) {
|
||||
struct stream_encoder *enc = pool->stream_enc[i];
|
||||
struct enc_state s = {0};
|
||||
|
||||
if (enc->funcs->enc_read_state) {
|
||||
enc->funcs->enc_read_state(enc, &s);
|
||||
DTN_INFO("[%-3d]: %-9d %-18d %-21d %-15d %-16d %-17d\n",
|
||||
enc->id,
|
||||
s.dsc_mode,
|
||||
s.sec_gsp7_line_num,
|
||||
s.vbid6_line_reference,
|
||||
s.vbid6_line_num,
|
||||
s.sec_gsp7_enable,
|
||||
s.sec_stream_enable);
|
||||
DTN_INFO("\n");
|
||||
}
|
||||
}
|
||||
DTN_INFO("\n");
|
||||
|
||||
DTN_INFO("L_ENC: DPHY_FEC_EN DPHY_FEC_READY_SHADOW DPHY_FEC_ACTIVE_STATUS\n");
|
||||
for (i = 0; i < dc->link_count; i++) {
|
||||
struct link_encoder *lenc = dc->links[i]->link_enc;
|
||||
|
||||
struct link_enc_state s = {0};
|
||||
|
||||
if (lenc->funcs->read_state) {
|
||||
lenc->funcs->read_state(lenc, &s);
|
||||
DTN_INFO("[%-3d]: %-12d %-22d %-22d\n",
|
||||
i,
|
||||
s.dphy_fec_en,
|
||||
s.dphy_fec_ready_shadow,
|
||||
s.dphy_fec_active_status);
|
||||
DTN_INFO("\n");
|
||||
}
|
||||
}
|
||||
DTN_INFO("\n");
|
||||
#endif
|
||||
|
||||
DTN_INFO("\nCALCULATED Clocks: dcfclk_khz:%d dcfclk_deep_sleep_khz:%d dispclk_khz:%d\n"
|
||||
"dppclk_khz:%d max_supported_dppclk_khz:%d fclk_khz:%d socclk_khz:%d\n\n",
|
||||
|
@ -1507,10 +1507,28 @@ void dcn10_timing_generator_init(struct optc *optc1)
|
||||
optc1->comb_opp_id = 0xf;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
/* "Containter" vs. "pixel" is a concept within HW blocks, mostly those closer to the back-end. It works like this:
|
||||
*
|
||||
* - In most of the formats (RGB or YCbCr 4:4:4, 4:2:2 uncompressed and DSC 4:2:2 Simple) pixel rate is the same as
|
||||
* containter rate.
|
||||
*
|
||||
* - In 4:2:0 (DSC or uncompressed) there are two pixels per container, hence the target container rate has to be
|
||||
* halved to maintain the correct pixel rate.
|
||||
*
|
||||
* - Unlike 4:2:2 uncompressed, DSC 4:2:2 Native also has two pixels per container (this happens when DSC is applied
|
||||
* to it) and has to be treated the same as 4:2:0, i.e. target containter rate has to be halved in this case as well.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
|
||||
{
|
||||
bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
|
||||
&& !timing->dsc_cfg.ycbcr422_simple);
|
||||
#endif
|
||||
return two_pix;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,10 @@ DCN20 = dcn20_resource.o dcn20_hwseq.o dcn20_dpp.o dcn20_dpp_cm.o dcn20_hubp.o \
|
||||
dcn20_stream_encoder.o dcn20_link_encoder.o dcn20_dccg.o \
|
||||
dcn20_vmid.o dcn20_dwb.o dcn20_dwb_scl.o
|
||||
|
||||
ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
DCN20 += dcn20_dsc.o
|
||||
endif
|
||||
|
||||
|
||||
CFLAGS_dcn20_resource.o := -mhard-float -msse -mpreferred-stack-boundary=4
|
||||
|
||||
|
688
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
Normal file
688
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
Normal file
@ -0,0 +1,688 @@
|
||||
/*
|
||||
* Copyright 2017 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
#include "reg_helper.h"
|
||||
#include "dcn20_dsc.h"
|
||||
#include "dsc/dscc_types.h"
|
||||
|
||||
static void dsc_log_pps(struct display_stream_compressor *dsc, struct drm_dsc_config *pps);
|
||||
static bool dsc_prepare_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
|
||||
struct dsc_optc_config *dsc_optc_cfg);
|
||||
static void dsc_init_reg_values(struct dsc_reg_values *reg_vals);
|
||||
static void dsc_update_from_dsc_parameters(struct dsc_reg_values *reg_vals, const struct dsc_parameters *dsc_params);
|
||||
static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals);
|
||||
static enum dsc_pixel_format dsc_dc_pixel_encoding_to_dsc_pixel_format(enum dc_pixel_encoding dc_pix_enc, bool is_ycbcr422_simple);
|
||||
static enum dsc_bits_per_comp dsc_dc_color_depth_to_dsc_bits_per_comp(enum dc_color_depth);
|
||||
|
||||
/* Object I/F functions */
|
||||
static void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz);
|
||||
static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s);
|
||||
static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg);
|
||||
static void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
|
||||
struct dsc_optc_config *dsc_optc_cfg, uint8_t *dsc_packed_pps);
|
||||
static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe);
|
||||
static void dsc2_disable(struct display_stream_compressor *dsc);
|
||||
|
||||
const struct dsc_funcs dcn20_dsc_funcs = {
|
||||
.dsc_get_enc_caps = dsc2_get_enc_caps,
|
||||
.dsc_read_state = dsc2_read_state,
|
||||
.dsc_validate_stream = dsc2_validate_stream,
|
||||
.dsc_set_config = dsc2_set_config,
|
||||
.dsc_enable = dsc2_enable,
|
||||
.dsc_disable = dsc2_disable,
|
||||
};
|
||||
|
||||
/* Macro definitios for REG_SET macros*/
|
||||
#define CTX \
|
||||
dsc20->base.ctx
|
||||
|
||||
#define REG(reg)\
|
||||
dsc20->dsc_regs->reg
|
||||
|
||||
#undef FN
|
||||
#define FN(reg_name, field_name) \
|
||||
dsc20->dsc_shift->field_name, dsc20->dsc_mask->field_name
|
||||
#define DC_LOGGER \
|
||||
dsc->ctx->logger
|
||||
|
||||
enum dsc_bits_per_comp {
|
||||
DSC_BPC_8 = 8,
|
||||
DSC_BPC_10 = 10,
|
||||
DSC_BPC_12 = 12,
|
||||
DSC_BPC_UNKNOWN
|
||||
};
|
||||
|
||||
/* API functions (external or via structure->function_pointer) */
|
||||
|
||||
void dsc2_construct(struct dcn20_dsc *dsc,
|
||||
struct dc_context *ctx,
|
||||
int inst,
|
||||
const struct dcn20_dsc_registers *dsc_regs,
|
||||
const struct dcn20_dsc_shift *dsc_shift,
|
||||
const struct dcn20_dsc_mask *dsc_mask)
|
||||
{
|
||||
dsc->base.ctx = ctx;
|
||||
dsc->base.inst = inst;
|
||||
dsc->base.funcs = &dcn20_dsc_funcs;
|
||||
|
||||
dsc->dsc_regs = dsc_regs;
|
||||
dsc->dsc_shift = dsc_shift;
|
||||
dsc->dsc_mask = dsc_mask;
|
||||
}
|
||||
|
||||
|
||||
#define DCN20_MAX_PIXEL_CLOCK_Mhz 1188
|
||||
#define DCN20_MAX_DISPLAY_CLOCK_Mhz 1200
|
||||
|
||||
/* This returns the capabilities for a single DSC encoder engine. Number of slices and total throughput
|
||||
* can be doubled, tripled etc. by using additional DSC engines.
|
||||
*/
|
||||
static void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz)
|
||||
{
|
||||
dsc_enc_caps->dsc_version = 0x21; /* v1.2 - DP spec defined it in reverse order and we kept it */
|
||||
|
||||
dsc_enc_caps->slice_caps.bits.NUM_SLICES_1 = 1;
|
||||
dsc_enc_caps->slice_caps.bits.NUM_SLICES_2 = 1;
|
||||
dsc_enc_caps->slice_caps.bits.NUM_SLICES_3 = 1;
|
||||
dsc_enc_caps->slice_caps.bits.NUM_SLICES_4 = 1;
|
||||
|
||||
dsc_enc_caps->lb_bit_depth = 13;
|
||||
dsc_enc_caps->is_block_pred_supported = true;
|
||||
|
||||
dsc_enc_caps->color_formats.bits.RGB = 1;
|
||||
dsc_enc_caps->color_formats.bits.YCBCR_444 = 1;
|
||||
dsc_enc_caps->color_formats.bits.YCBCR_SIMPLE_422 = 1;
|
||||
dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_422 = 1;
|
||||
dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_420 = 1;
|
||||
|
||||
dsc_enc_caps->color_depth.bits.COLOR_DEPTH_8_BPC = 1;
|
||||
dsc_enc_caps->color_depth.bits.COLOR_DEPTH_10_BPC = 1;
|
||||
dsc_enc_caps->color_depth.bits.COLOR_DEPTH_12_BPC = 1;
|
||||
|
||||
/* Maximum total throughput with all the slices combined. This is different from how DP spec specifies it.
|
||||
* Our decoder's total throughput in Pix/s is equal to DISPCLK. This is then shared between slices.
|
||||
* The value below is the absolute maximum value. The actual througput may be lower, but it'll always
|
||||
* be sufficient to process the input pixel rate fed into a single DSC engine.
|
||||
*/
|
||||
dsc_enc_caps->max_total_throughput_mps = DCN20_MAX_DISPLAY_CLOCK_Mhz;
|
||||
|
||||
/* For pixel clock bigger than a single-pipe limit we'll need two engines, which then doubles our
|
||||
* throughput and number of slices, but also introduces a lower limit of 2 slices
|
||||
*/
|
||||
if (pixel_clock_100Hz >= DCN20_MAX_PIXEL_CLOCK_Mhz*10000) {
|
||||
dsc_enc_caps->slice_caps.bits.NUM_SLICES_1 = 0;
|
||||
dsc_enc_caps->slice_caps.bits.NUM_SLICES_8 = 1;
|
||||
dsc_enc_caps->max_total_throughput_mps = DCN20_MAX_DISPLAY_CLOCK_Mhz * 2;
|
||||
}
|
||||
|
||||
// TODO DSC: This is actually image width limitation, not a slice width. This should be added to the criteria to use ODM.
|
||||
dsc_enc_caps->max_slice_width = 5184; /* (including 64 overlap pixels for eDP MSO mode) */
|
||||
dsc_enc_caps->bpp_increment_div = 16; /* 1/16th of a bit */
|
||||
}
|
||||
|
||||
|
||||
/* this function read dsc related register fields to be logged later in dcn10_log_hw_state
|
||||
* into a dcn_dsc_state struct.
|
||||
*/
|
||||
static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s)
|
||||
{
|
||||
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
|
||||
|
||||
REG_GET(DSC_TOP_CONTROL, DSC_CLOCK_EN, &s->dsc_clock_en);
|
||||
REG_GET(DSCC_PPS_CONFIG3, SLICE_WIDTH, &s->dsc_slice_width);
|
||||
REG_GET(DSCC_PPS_CONFIG1, BITS_PER_PIXEL, &s->dsc_bytes_per_pixel);
|
||||
}
|
||||
|
||||
|
||||
static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg)
|
||||
{
|
||||
struct dsc_optc_config dsc_optc_cfg;
|
||||
|
||||
return dsc_prepare_config(dsc, dsc_cfg, &dsc_optc_cfg);
|
||||
}
|
||||
|
||||
|
||||
static void dsc_config_log(struct display_stream_compressor *dsc,
|
||||
const struct dsc_config *config)
|
||||
{
|
||||
DC_LOG_DSC("Setting DSC Config at DSC inst %d", dsc->inst);
|
||||
DC_LOG_DSC("\n\tnum_slices_h %d\n\tnum_slices_v %d\n\tbits_per_pixel %d\n\tcolor_depth %d",
|
||||
config->dc_dsc_cfg.num_slices_h,
|
||||
config->dc_dsc_cfg.num_slices_v,
|
||||
config->dc_dsc_cfg.bits_per_pixel,
|
||||
config->color_depth);
|
||||
}
|
||||
|
||||
static void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
|
||||
struct dsc_optc_config *dsc_optc_cfg, uint8_t *dsc_packed_pps)
|
||||
{
|
||||
bool is_config_ok;
|
||||
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
|
||||
|
||||
dsc_config_log(dsc, dsc_cfg);
|
||||
is_config_ok = dsc_prepare_config(dsc, dsc_cfg, dsc_optc_cfg);
|
||||
ASSERT(is_config_ok);
|
||||
drm_dsc_pps_payload_pack((struct drm_dsc_picture_parameter_set *)dsc_packed_pps, &dsc20->reg_vals.pps);
|
||||
dsc_log_pps(dsc, &dsc20->reg_vals.pps);
|
||||
dsc_write_to_registers(dsc, &dsc20->reg_vals);
|
||||
}
|
||||
|
||||
|
||||
static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe)
|
||||
{
|
||||
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
|
||||
|
||||
/* TODO Check if DSC alreay in use? */
|
||||
DC_LOG_DSC("enable DSC at opp pipe %d", opp_pipe);
|
||||
|
||||
REG_UPDATE(DSC_TOP_CONTROL,
|
||||
DSC_CLOCK_EN, 1);
|
||||
|
||||
REG_UPDATE_2(DSCRM_DSC_FORWARD_CONFIG,
|
||||
DSCRM_DSC_FORWARD_EN, 1,
|
||||
DSCRM_DSC_OPP_PIPE_SOURCE, opp_pipe);
|
||||
}
|
||||
|
||||
|
||||
static void dsc2_disable(struct display_stream_compressor *dsc)
|
||||
{
|
||||
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
|
||||
|
||||
DC_LOG_DSC("disable DSC");
|
||||
|
||||
REG_UPDATE(DSCRM_DSC_FORWARD_CONFIG,
|
||||
DSCRM_DSC_FORWARD_EN, 0);
|
||||
|
||||
REG_UPDATE(DSC_TOP_CONTROL,
|
||||
DSC_CLOCK_EN, 0);
|
||||
}
|
||||
|
||||
|
||||
/* This module's internal functions */
|
||||
static void dsc_log_pps(struct display_stream_compressor *dsc, struct drm_dsc_config *pps)
|
||||
{
|
||||
int i;
|
||||
|
||||
DC_LOG_DSC("programming DSC Picture Parameter Set (PPS):");
|
||||
DC_LOG_DSC("\tdsc_version_major %d", pps->dsc_version_major);
|
||||
DC_LOG_DSC("\tdsc_version_minor %d", pps->dsc_version_minor);
|
||||
DC_LOG_DSC("\tbits_per_component %d", pps->bits_per_component);
|
||||
DC_LOG_DSC("\tline_buf_depth %d", pps->line_buf_depth);
|
||||
DC_LOG_DSC("\tblock_pred_enable %d", pps->block_pred_enable);
|
||||
DC_LOG_DSC("\tconvert_rgb %d", pps->convert_rgb);
|
||||
DC_LOG_DSC("\tsimple_422 %d", pps->simple_422);
|
||||
DC_LOG_DSC("\tvbr_enable %d", pps->vbr_enable);
|
||||
DC_LOG_DSC("\tbits_per_pixel %d", pps->bits_per_pixel);
|
||||
DC_LOG_DSC("\tpic_height %d", pps->pic_height);
|
||||
DC_LOG_DSC("\tpic_width %d", pps->pic_width);
|
||||
DC_LOG_DSC("\tslice_height %d", pps->slice_height);
|
||||
DC_LOG_DSC("\tslice_width %d", pps->slice_width);
|
||||
DC_LOG_DSC("\tslice_chunk_size %d", pps->slice_chunk_size);
|
||||
DC_LOG_DSC("\tinitial_xmit_delay %d", pps->initial_xmit_delay);
|
||||
DC_LOG_DSC("\tinitial_dec_delay %d", pps->initial_dec_delay);
|
||||
DC_LOG_DSC("\tinitial_scale_value %d", pps->initial_scale_value);
|
||||
DC_LOG_DSC("\tscale_increment_interval %d", pps->scale_increment_interval);
|
||||
DC_LOG_DSC("\tscale_decrement_interval %d", pps->scale_decrement_interval);
|
||||
DC_LOG_DSC("\tfirst_line_bpg_offset %d", pps->first_line_bpg_offset);
|
||||
DC_LOG_DSC("\tnfl_bpg_offset %d", pps->nfl_bpg_offset);
|
||||
DC_LOG_DSC("\tslice_bpg_offset %d", pps->slice_bpg_offset);
|
||||
DC_LOG_DSC("\tinitial_offset %d", pps->initial_offset);
|
||||
DC_LOG_DSC("\tfinal_offset %d", pps->final_offset);
|
||||
DC_LOG_DSC("\tflatness_min_qp %d", pps->flatness_min_qp);
|
||||
DC_LOG_DSC("\tflatness_max_qp %d", pps->flatness_max_qp);
|
||||
/* DC_LOG_DSC("\trc_parameter_set %d", pps->rc_parameter_set); */
|
||||
DC_LOG_DSC("\tnative_420 %d", pps->native_420);
|
||||
DC_LOG_DSC("\tnative_422 %d", pps->native_422);
|
||||
DC_LOG_DSC("\tsecond_line_bpg_offset %d", pps->second_line_bpg_offset);
|
||||
DC_LOG_DSC("\tnsl_bpg_offset %d", pps->nsl_bpg_offset);
|
||||
DC_LOG_DSC("\tsecond_line_offset_adj %d", pps->second_line_offset_adj);
|
||||
DC_LOG_DSC("\trc_model_size %d", pps->rc_model_size);
|
||||
DC_LOG_DSC("\trc_edge_factor %d", pps->rc_edge_factor);
|
||||
DC_LOG_DSC("\trc_quant_incr_limit0 %d", pps->rc_quant_incr_limit0);
|
||||
DC_LOG_DSC("\trc_quant_incr_limit1 %d", pps->rc_quant_incr_limit1);
|
||||
DC_LOG_DSC("\trc_tgt_offset_high %d", pps->rc_tgt_offset_high);
|
||||
DC_LOG_DSC("\trc_tgt_offset_low %d", pps->rc_tgt_offset_low);
|
||||
|
||||
for (i = 0; i < NUM_BUF_RANGES - 1; i++)
|
||||
DC_LOG_DSC("\trc_buf_thresh[%d] %d", i, pps->rc_buf_thresh[i]);
|
||||
|
||||
for (i = 0; i < NUM_BUF_RANGES; i++) {
|
||||
DC_LOG_DSC("\trc_range_parameters[%d].range_min_qp %d", i, pps->rc_range_params[i].range_min_qp);
|
||||
DC_LOG_DSC("\trc_range_parameters[%d].range_max_qp %d", i, pps->rc_range_params[i].range_max_qp);
|
||||
DC_LOG_DSC("\trc_range_parameters[%d].range_bpg_offset %d", i, pps->rc_range_params[i].range_bpg_offset);
|
||||
}
|
||||
}
|
||||
|
||||
static bool dsc_prepare_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
|
||||
struct dsc_optc_config *dsc_optc_cfg)
|
||||
{
|
||||
struct dsc_parameters dsc_params;
|
||||
|
||||
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
|
||||
|
||||
/* Validate input parameters */
|
||||
ASSERT(dsc_cfg->dc_dsc_cfg.num_slices_h);
|
||||
ASSERT(dsc_cfg->dc_dsc_cfg.num_slices_v);
|
||||
ASSERT(dsc_cfg->dc_dsc_cfg.version_minor == 1 || dsc_cfg->dc_dsc_cfg.version_minor == 2);
|
||||
ASSERT(dsc_cfg->pic_width);
|
||||
ASSERT(dsc_cfg->pic_height);
|
||||
ASSERT((dsc_cfg->dc_dsc_cfg.version_minor == 1 &&
|
||||
(8 <= dsc_cfg->dc_dsc_cfg.linebuf_depth && dsc_cfg->dc_dsc_cfg.linebuf_depth <= 13)) ||
|
||||
(dsc_cfg->dc_dsc_cfg.version_minor == 2 &&
|
||||
((8 <= dsc_cfg->dc_dsc_cfg.linebuf_depth && dsc_cfg->dc_dsc_cfg.linebuf_depth <= 15) ||
|
||||
dsc_cfg->dc_dsc_cfg.linebuf_depth == 0)));
|
||||
ASSERT(96 <= dsc_cfg->dc_dsc_cfg.bits_per_pixel && dsc_cfg->dc_dsc_cfg.bits_per_pixel <= 0x3ff); // 6.0 <= bits_per_pixel <= 63.9375
|
||||
|
||||
if (!dsc_cfg->dc_dsc_cfg.num_slices_v || !dsc_cfg->dc_dsc_cfg.num_slices_v ||
|
||||
!(dsc_cfg->dc_dsc_cfg.version_minor == 1 || dsc_cfg->dc_dsc_cfg.version_minor == 2) ||
|
||||
!dsc_cfg->pic_width || !dsc_cfg->pic_height ||
|
||||
!((dsc_cfg->dc_dsc_cfg.version_minor == 1 && // v1.1 line buffer depth range:
|
||||
8 <= dsc_cfg->dc_dsc_cfg.linebuf_depth && dsc_cfg->dc_dsc_cfg.linebuf_depth <= 13) ||
|
||||
(dsc_cfg->dc_dsc_cfg.version_minor == 2 && // v1.2 line buffer depth range:
|
||||
((8 <= dsc_cfg->dc_dsc_cfg.linebuf_depth && dsc_cfg->dc_dsc_cfg.linebuf_depth <= 15) ||
|
||||
dsc_cfg->dc_dsc_cfg.linebuf_depth == 0))) ||
|
||||
!(96 <= dsc_cfg->dc_dsc_cfg.bits_per_pixel && dsc_cfg->dc_dsc_cfg.bits_per_pixel <= 0x3ff)) {
|
||||
dm_output_to_console("%s: Invalid parameters\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
dsc_init_reg_values(&dsc20->reg_vals);
|
||||
|
||||
/* Copy input config */
|
||||
dsc20->reg_vals.pixel_format = dsc_dc_pixel_encoding_to_dsc_pixel_format(dsc_cfg->pixel_encoding, dsc_cfg->dc_dsc_cfg.ycbcr422_simple);
|
||||
dsc20->reg_vals.num_slices_h = dsc_cfg->dc_dsc_cfg.num_slices_h;
|
||||
dsc20->reg_vals.num_slices_v = dsc_cfg->dc_dsc_cfg.num_slices_v;
|
||||
dsc20->reg_vals.pps.dsc_version_minor = dsc_cfg->dc_dsc_cfg.version_minor;
|
||||
dsc20->reg_vals.pps.pic_width = dsc_cfg->pic_width;
|
||||
dsc20->reg_vals.pps.pic_height = dsc_cfg->pic_height;
|
||||
dsc20->reg_vals.pps.bits_per_component = dsc_dc_color_depth_to_dsc_bits_per_comp(dsc_cfg->color_depth);
|
||||
dsc20->reg_vals.pps.block_pred_enable = dsc_cfg->dc_dsc_cfg.block_pred_enable;
|
||||
dsc20->reg_vals.pps.line_buf_depth = dsc_cfg->dc_dsc_cfg.linebuf_depth;
|
||||
dsc20->reg_vals.alternate_ich_encoding_en = dsc20->reg_vals.pps.dsc_version_minor == 1 ? 0 : 1;
|
||||
|
||||
// TODO: in addition to validating slice height (pic height must be divisible by slice height),
|
||||
// see what happens when the same condition doesn't apply for slice_width/pic_width.
|
||||
dsc20->reg_vals.pps.slice_width = dsc_cfg->pic_width / dsc_cfg->dc_dsc_cfg.num_slices_h;
|
||||
dsc20->reg_vals.pps.slice_height = dsc_cfg->pic_height / dsc_cfg->dc_dsc_cfg.num_slices_v;
|
||||
|
||||
ASSERT(dsc20->reg_vals.pps.slice_height * dsc_cfg->dc_dsc_cfg.num_slices_v == dsc_cfg->pic_height);
|
||||
if (!(dsc20->reg_vals.pps.slice_height * dsc_cfg->dc_dsc_cfg.num_slices_v == dsc_cfg->pic_height)) {
|
||||
dm_output_to_console("%s: pix height %d not divisible by num_slices_v %d\n\n", __func__, dsc_cfg->pic_height, dsc_cfg->dc_dsc_cfg.num_slices_v);
|
||||
return false;
|
||||
}
|
||||
|
||||
dsc20->reg_vals.bpp_x32 = dsc_cfg->dc_dsc_cfg.bits_per_pixel << 1;
|
||||
if (dsc20->reg_vals.pixel_format == DSC_PIXFMT_NATIVE_YCBCR420 || dsc20->reg_vals.pixel_format == DSC_PIXFMT_NATIVE_YCBCR422)
|
||||
dsc20->reg_vals.pps.bits_per_pixel = dsc20->reg_vals.bpp_x32;
|
||||
else
|
||||
dsc20->reg_vals.pps.bits_per_pixel = dsc20->reg_vals.bpp_x32 >> 1;
|
||||
|
||||
dsc20->reg_vals.pps.convert_rgb = dsc20->reg_vals.pixel_format == DSC_PIXFMT_RGB ? 1 : 0;
|
||||
dsc20->reg_vals.pps.native_422 = (dsc20->reg_vals.pixel_format == DSC_PIXFMT_NATIVE_YCBCR422);
|
||||
dsc20->reg_vals.pps.native_420 = (dsc20->reg_vals.pixel_format == DSC_PIXFMT_NATIVE_YCBCR420);
|
||||
dsc20->reg_vals.pps.simple_422 = (dsc20->reg_vals.pixel_format == DSC_PIXFMT_SIMPLE_YCBCR422);
|
||||
|
||||
if (dscc_compute_dsc_parameters(&dsc20->reg_vals.pps, &dsc_params)) {
|
||||
dm_output_to_console("%s: DSC config failed\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
dsc_update_from_dsc_parameters(&dsc20->reg_vals, &dsc_params);
|
||||
|
||||
dsc_optc_cfg->bytes_per_pixel = dsc_params.bytes_per_pixel;
|
||||
dsc_optc_cfg->slice_width = dsc20->reg_vals.pps.slice_width;
|
||||
dsc_optc_cfg->is_pixel_format_444 = dsc20->reg_vals.pixel_format == DSC_PIXFMT_RGB ||
|
||||
dsc20->reg_vals.pixel_format == DSC_PIXFMT_YCBCR444 ||
|
||||
dsc20->reg_vals.pixel_format == DSC_PIXFMT_SIMPLE_YCBCR422;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static enum dsc_pixel_format dsc_dc_pixel_encoding_to_dsc_pixel_format(enum dc_pixel_encoding dc_pix_enc, bool is_ycbcr422_simple)
|
||||
{
|
||||
enum dsc_pixel_format dsc_pix_fmt = DSC_PIXFMT_UNKNOWN;
|
||||
|
||||
/* NOTE: We don't support DSC_PIXFMT_SIMPLE_YCBCR422 */
|
||||
|
||||
switch (dc_pix_enc) {
|
||||
case PIXEL_ENCODING_RGB:
|
||||
dsc_pix_fmt = DSC_PIXFMT_RGB;
|
||||
break;
|
||||
case PIXEL_ENCODING_YCBCR422:
|
||||
if (is_ycbcr422_simple)
|
||||
dsc_pix_fmt = DSC_PIXFMT_SIMPLE_YCBCR422;
|
||||
else
|
||||
dsc_pix_fmt = DSC_PIXFMT_NATIVE_YCBCR422;
|
||||
break;
|
||||
case PIXEL_ENCODING_YCBCR444:
|
||||
dsc_pix_fmt = DSC_PIXFMT_YCBCR444;
|
||||
break;
|
||||
case PIXEL_ENCODING_YCBCR420:
|
||||
dsc_pix_fmt = DSC_PIXFMT_NATIVE_YCBCR420;
|
||||
break;
|
||||
default:
|
||||
dsc_pix_fmt = DSC_PIXFMT_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT(dsc_pix_fmt != DSC_PIXFMT_UNKNOWN);
|
||||
return dsc_pix_fmt;
|
||||
}
|
||||
|
||||
|
||||
static enum dsc_bits_per_comp dsc_dc_color_depth_to_dsc_bits_per_comp(enum dc_color_depth dc_color_depth)
|
||||
{
|
||||
enum dsc_bits_per_comp bpc = DSC_BPC_UNKNOWN;
|
||||
|
||||
switch (dc_color_depth) {
|
||||
case COLOR_DEPTH_888:
|
||||
bpc = DSC_BPC_8;
|
||||
break;
|
||||
case COLOR_DEPTH_101010:
|
||||
bpc = DSC_BPC_10;
|
||||
break;
|
||||
case COLOR_DEPTH_121212:
|
||||
bpc = DSC_BPC_12;
|
||||
break;
|
||||
default:
|
||||
bpc = DSC_BPC_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return bpc;
|
||||
}
|
||||
|
||||
|
||||
static void dsc_init_reg_values(struct dsc_reg_values *reg_vals)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Non-PPS values */
|
||||
reg_vals->dsc_clock_enable = 1;
|
||||
reg_vals->dsc_clock_gating_disable = 0;
|
||||
reg_vals->underflow_recovery_en = 0;
|
||||
reg_vals->underflow_occurred_int_en = 0;
|
||||
reg_vals->underflow_occurred_status = 0;
|
||||
reg_vals->ich_reset_at_eol = 0;
|
||||
reg_vals->alternate_ich_encoding_en = 0;
|
||||
reg_vals->rc_buffer_model_size = 0;
|
||||
reg_vals->disable_ich = 0;
|
||||
reg_vals->dsc_dbg_en = 0;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
reg_vals->rc_buffer_model_overflow_int_en[i] = 0;
|
||||
|
||||
/* PPS values */
|
||||
reg_vals->pps.dsc_version_minor = 2;
|
||||
reg_vals->pps.dsc_version_major = 1;
|
||||
reg_vals->pps.line_buf_depth = 9;
|
||||
reg_vals->pps.bits_per_component = 8;
|
||||
reg_vals->pps.block_pred_enable = 1;
|
||||
reg_vals->pps.slice_chunk_size = 0;
|
||||
reg_vals->pps.pic_width = 0;
|
||||
reg_vals->pps.pic_height = 0;
|
||||
reg_vals->pps.slice_width = 0;
|
||||
reg_vals->pps.slice_height = 0;
|
||||
reg_vals->pps.initial_xmit_delay = 170;
|
||||
reg_vals->pps.initial_dec_delay = 0;
|
||||
reg_vals->pps.initial_scale_value = 0;
|
||||
reg_vals->pps.scale_increment_interval = 0;
|
||||
reg_vals->pps.scale_decrement_interval = 0;
|
||||
reg_vals->pps.nfl_bpg_offset = 0;
|
||||
reg_vals->pps.slice_bpg_offset = 0;
|
||||
reg_vals->pps.nsl_bpg_offset = 0;
|
||||
reg_vals->pps.initial_offset = 6144;
|
||||
reg_vals->pps.final_offset = 0;
|
||||
reg_vals->pps.flatness_min_qp = 3;
|
||||
reg_vals->pps.flatness_max_qp = 12;
|
||||
reg_vals->pps.rc_model_size = 8192;
|
||||
reg_vals->pps.rc_edge_factor = 6;
|
||||
reg_vals->pps.rc_quant_incr_limit0 = 11;
|
||||
reg_vals->pps.rc_quant_incr_limit1 = 11;
|
||||
reg_vals->pps.rc_tgt_offset_low = 3;
|
||||
reg_vals->pps.rc_tgt_offset_high = 3;
|
||||
}
|
||||
|
||||
/* Updates dsc_reg_values::reg_vals::xxx fields based on the values from computed params.
|
||||
* This is required because dscc_compute_dsc_parameters returns a modified PPS, which in turn
|
||||
* affects non-PPS register values.
|
||||
*/
|
||||
static void dsc_update_from_dsc_parameters(struct dsc_reg_values *reg_vals, const struct dsc_parameters *dsc_params)
|
||||
{
|
||||
int i;
|
||||
|
||||
reg_vals->pps = dsc_params->pps;
|
||||
|
||||
// pps_computed will have the "expanded" values; need to shift them to make them fit for regs.
|
||||
for (i = 0; i < NUM_BUF_RANGES - 1; i++)
|
||||
reg_vals->pps.rc_buf_thresh[i] = reg_vals->pps.rc_buf_thresh[i] >> 6;
|
||||
|
||||
reg_vals->rc_buffer_model_size = dsc_params->rc_buffer_model_size;
|
||||
reg_vals->ich_reset_at_eol = reg_vals->num_slices_h == 1 ? 0 : 0xf;
|
||||
}
|
||||
|
||||
static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals)
|
||||
{
|
||||
uint32_t temp_int;
|
||||
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
|
||||
|
||||
REG_SET(DSC_DEBUG_CONTROL, 0,
|
||||
DSC_DBG_EN, reg_vals->dsc_dbg_en);
|
||||
|
||||
// dsccif registers
|
||||
REG_SET_5(DSCCIF_CONFIG0, 0,
|
||||
INPUT_INTERFACE_UNDERFLOW_RECOVERY_EN, reg_vals->underflow_recovery_en,
|
||||
INPUT_INTERFACE_UNDERFLOW_OCCURRED_INT_EN, reg_vals->underflow_occurred_int_en,
|
||||
INPUT_INTERFACE_UNDERFLOW_OCCURRED_STATUS, reg_vals->underflow_occurred_status,
|
||||
INPUT_PIXEL_FORMAT, reg_vals->pixel_format,
|
||||
DSCCIF_CONFIG0__BITS_PER_COMPONENT, reg_vals->pps.bits_per_component);
|
||||
|
||||
REG_SET_2(DSCCIF_CONFIG1, 0,
|
||||
PIC_WIDTH, reg_vals->pps.pic_width,
|
||||
PIC_HEIGHT, reg_vals->pps.pic_height);
|
||||
|
||||
// dscc registers
|
||||
REG_SET_4(DSCC_CONFIG0, 0,
|
||||
ICH_RESET_AT_END_OF_LINE, reg_vals->ich_reset_at_eol,
|
||||
NUMBER_OF_SLICES_PER_LINE, reg_vals->num_slices_h - 1,
|
||||
ALTERNATE_ICH_ENCODING_EN, reg_vals->alternate_ich_encoding_en,
|
||||
NUMBER_OF_SLICES_IN_VERTICAL_DIRECTION, reg_vals->num_slices_v - 1);
|
||||
|
||||
REG_SET_2(DSCC_CONFIG1, 0,
|
||||
DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE, reg_vals->rc_buffer_model_size,
|
||||
DSCC_DISABLE_ICH, reg_vals->disable_ich);
|
||||
|
||||
REG_SET_4(DSCC_INTERRUPT_CONTROL_STATUS, 0,
|
||||
DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED_INT_EN, reg_vals->rc_buffer_model_overflow_int_en[0],
|
||||
DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED_INT_EN, reg_vals->rc_buffer_model_overflow_int_en[1],
|
||||
DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED_INT_EN, reg_vals->rc_buffer_model_overflow_int_en[2],
|
||||
DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED_INT_EN, reg_vals->rc_buffer_model_overflow_int_en[3]);
|
||||
|
||||
REG_SET_3(DSCC_PPS_CONFIG0, 0,
|
||||
DSC_VERSION_MINOR, reg_vals->pps.dsc_version_minor,
|
||||
LINEBUF_DEPTH, reg_vals->pps.line_buf_depth,
|
||||
DSCC_PPS_CONFIG0__BITS_PER_COMPONENT, reg_vals->pps.bits_per_component);
|
||||
|
||||
if (reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR420 || reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR422)
|
||||
temp_int = reg_vals->bpp_x32;
|
||||
else
|
||||
temp_int = reg_vals->bpp_x32 >> 1;
|
||||
|
||||
REG_SET_7(DSCC_PPS_CONFIG1, 0,
|
||||
BITS_PER_PIXEL, temp_int,
|
||||
SIMPLE_422, reg_vals->pixel_format == DSC_PIXFMT_SIMPLE_YCBCR422,
|
||||
CONVERT_RGB, reg_vals->pixel_format == DSC_PIXFMT_RGB,
|
||||
BLOCK_PRED_ENABLE, reg_vals->pps.block_pred_enable,
|
||||
NATIVE_422, reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR422,
|
||||
NATIVE_420, reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR420,
|
||||
CHUNK_SIZE, reg_vals->pps.slice_chunk_size);
|
||||
|
||||
REG_SET_2(DSCC_PPS_CONFIG2, 0,
|
||||
PIC_WIDTH, reg_vals->pps.pic_width,
|
||||
PIC_HEIGHT, reg_vals->pps.pic_height);
|
||||
|
||||
REG_SET_2(DSCC_PPS_CONFIG3, 0,
|
||||
SLICE_WIDTH, reg_vals->pps.slice_width,
|
||||
SLICE_HEIGHT, reg_vals->pps.slice_height);
|
||||
|
||||
REG_SET(DSCC_PPS_CONFIG4, 0,
|
||||
INITIAL_XMIT_DELAY, reg_vals->pps.initial_xmit_delay);
|
||||
|
||||
REG_SET_2(DSCC_PPS_CONFIG5, 0,
|
||||
INITIAL_SCALE_VALUE, reg_vals->pps.initial_scale_value,
|
||||
SCALE_INCREMENT_INTERVAL, reg_vals->pps.scale_increment_interval);
|
||||
|
||||
REG_SET_3(DSCC_PPS_CONFIG6, 0,
|
||||
SCALE_DECREMENT_INTERVAL, reg_vals->pps.scale_decrement_interval,
|
||||
FIRST_LINE_BPG_OFFSET, reg_vals->pps.first_line_bpg_offset,
|
||||
SECOND_LINE_BPG_OFFSET, reg_vals->pps.second_line_bpg_offset);
|
||||
|
||||
REG_SET_2(DSCC_PPS_CONFIG7, 0,
|
||||
NFL_BPG_OFFSET, reg_vals->pps.nfl_bpg_offset,
|
||||
SLICE_BPG_OFFSET, reg_vals->pps.slice_bpg_offset);
|
||||
|
||||
REG_SET_2(DSCC_PPS_CONFIG8, 0,
|
||||
NSL_BPG_OFFSET, reg_vals->pps.nsl_bpg_offset,
|
||||
SECOND_LINE_OFFSET_ADJ, reg_vals->pps.second_line_offset_adj);
|
||||
|
||||
REG_SET_2(DSCC_PPS_CONFIG9, 0,
|
||||
INITIAL_OFFSET, reg_vals->pps.initial_offset,
|
||||
FINAL_OFFSET, reg_vals->pps.final_offset);
|
||||
|
||||
REG_SET_3(DSCC_PPS_CONFIG10, 0,
|
||||
FLATNESS_MIN_QP, reg_vals->pps.flatness_min_qp,
|
||||
FLATNESS_MAX_QP, reg_vals->pps.flatness_max_qp,
|
||||
RC_MODEL_SIZE, reg_vals->pps.rc_model_size);
|
||||
|
||||
REG_SET_5(DSCC_PPS_CONFIG11, 0,
|
||||
RC_EDGE_FACTOR, reg_vals->pps.rc_edge_factor,
|
||||
RC_QUANT_INCR_LIMIT0, reg_vals->pps.rc_quant_incr_limit0,
|
||||
RC_QUANT_INCR_LIMIT1, reg_vals->pps.rc_quant_incr_limit1,
|
||||
RC_TGT_OFFSET_LO, reg_vals->pps.rc_tgt_offset_low,
|
||||
RC_TGT_OFFSET_HI, reg_vals->pps.rc_tgt_offset_high);
|
||||
|
||||
REG_SET_4(DSCC_PPS_CONFIG12, 0,
|
||||
RC_BUF_THRESH0, reg_vals->pps.rc_buf_thresh[0],
|
||||
RC_BUF_THRESH1, reg_vals->pps.rc_buf_thresh[1],
|
||||
RC_BUF_THRESH2, reg_vals->pps.rc_buf_thresh[2],
|
||||
RC_BUF_THRESH3, reg_vals->pps.rc_buf_thresh[3]);
|
||||
|
||||
REG_SET_4(DSCC_PPS_CONFIG13, 0,
|
||||
RC_BUF_THRESH4, reg_vals->pps.rc_buf_thresh[4],
|
||||
RC_BUF_THRESH5, reg_vals->pps.rc_buf_thresh[5],
|
||||
RC_BUF_THRESH6, reg_vals->pps.rc_buf_thresh[6],
|
||||
RC_BUF_THRESH7, reg_vals->pps.rc_buf_thresh[7]);
|
||||
|
||||
REG_SET_4(DSCC_PPS_CONFIG14, 0,
|
||||
RC_BUF_THRESH8, reg_vals->pps.rc_buf_thresh[8],
|
||||
RC_BUF_THRESH9, reg_vals->pps.rc_buf_thresh[9],
|
||||
RC_BUF_THRESH10, reg_vals->pps.rc_buf_thresh[10],
|
||||
RC_BUF_THRESH11, reg_vals->pps.rc_buf_thresh[11]);
|
||||
|
||||
REG_SET_5(DSCC_PPS_CONFIG15, 0,
|
||||
RC_BUF_THRESH12, reg_vals->pps.rc_buf_thresh[12],
|
||||
RC_BUF_THRESH13, reg_vals->pps.rc_buf_thresh[13],
|
||||
RANGE_MIN_QP0, reg_vals->pps.rc_range_params[0].range_min_qp,
|
||||
RANGE_MAX_QP0, reg_vals->pps.rc_range_params[0].range_max_qp,
|
||||
RANGE_BPG_OFFSET0, reg_vals->pps.rc_range_params[0].range_bpg_offset);
|
||||
|
||||
REG_SET_6(DSCC_PPS_CONFIG16, 0,
|
||||
RANGE_MIN_QP1, reg_vals->pps.rc_range_params[1].range_min_qp,
|
||||
RANGE_MAX_QP1, reg_vals->pps.rc_range_params[1].range_max_qp,
|
||||
RANGE_BPG_OFFSET1, reg_vals->pps.rc_range_params[1].range_bpg_offset,
|
||||
RANGE_MIN_QP2, reg_vals->pps.rc_range_params[2].range_min_qp,
|
||||
RANGE_MAX_QP2, reg_vals->pps.rc_range_params[2].range_max_qp,
|
||||
RANGE_BPG_OFFSET2, reg_vals->pps.rc_range_params[2].range_bpg_offset);
|
||||
|
||||
REG_SET_6(DSCC_PPS_CONFIG17, 0,
|
||||
RANGE_MIN_QP3, reg_vals->pps.rc_range_params[3].range_min_qp,
|
||||
RANGE_MAX_QP3, reg_vals->pps.rc_range_params[3].range_max_qp,
|
||||
RANGE_BPG_OFFSET3, reg_vals->pps.rc_range_params[3].range_bpg_offset,
|
||||
RANGE_MIN_QP4, reg_vals->pps.rc_range_params[4].range_min_qp,
|
||||
RANGE_MAX_QP4, reg_vals->pps.rc_range_params[4].range_max_qp,
|
||||
RANGE_BPG_OFFSET4, reg_vals->pps.rc_range_params[4].range_bpg_offset);
|
||||
|
||||
REG_SET_6(DSCC_PPS_CONFIG18, 0,
|
||||
RANGE_MIN_QP5, reg_vals->pps.rc_range_params[5].range_min_qp,
|
||||
RANGE_MAX_QP5, reg_vals->pps.rc_range_params[5].range_max_qp,
|
||||
RANGE_BPG_OFFSET5, reg_vals->pps.rc_range_params[5].range_bpg_offset,
|
||||
RANGE_MIN_QP6, reg_vals->pps.rc_range_params[6].range_min_qp,
|
||||
RANGE_MAX_QP6, reg_vals->pps.rc_range_params[6].range_max_qp,
|
||||
RANGE_BPG_OFFSET6, reg_vals->pps.rc_range_params[6].range_bpg_offset);
|
||||
|
||||
REG_SET_6(DSCC_PPS_CONFIG19, 0,
|
||||
RANGE_MIN_QP7, reg_vals->pps.rc_range_params[7].range_min_qp,
|
||||
RANGE_MAX_QP7, reg_vals->pps.rc_range_params[7].range_max_qp,
|
||||
RANGE_BPG_OFFSET7, reg_vals->pps.rc_range_params[7].range_bpg_offset,
|
||||
RANGE_MIN_QP8, reg_vals->pps.rc_range_params[8].range_min_qp,
|
||||
RANGE_MAX_QP8, reg_vals->pps.rc_range_params[8].range_max_qp,
|
||||
RANGE_BPG_OFFSET8, reg_vals->pps.rc_range_params[8].range_bpg_offset);
|
||||
|
||||
REG_SET_6(DSCC_PPS_CONFIG20, 0,
|
||||
RANGE_MIN_QP9, reg_vals->pps.rc_range_params[9].range_min_qp,
|
||||
RANGE_MAX_QP9, reg_vals->pps.rc_range_params[9].range_max_qp,
|
||||
RANGE_BPG_OFFSET9, reg_vals->pps.rc_range_params[9].range_bpg_offset,
|
||||
RANGE_MIN_QP10, reg_vals->pps.rc_range_params[10].range_min_qp,
|
||||
RANGE_MAX_QP10, reg_vals->pps.rc_range_params[10].range_max_qp,
|
||||
RANGE_BPG_OFFSET10, reg_vals->pps.rc_range_params[10].range_bpg_offset);
|
||||
|
||||
REG_SET_6(DSCC_PPS_CONFIG21, 0,
|
||||
RANGE_MIN_QP11, reg_vals->pps.rc_range_params[11].range_min_qp,
|
||||
RANGE_MAX_QP11, reg_vals->pps.rc_range_params[11].range_max_qp,
|
||||
RANGE_BPG_OFFSET11, reg_vals->pps.rc_range_params[11].range_bpg_offset,
|
||||
RANGE_MIN_QP12, reg_vals->pps.rc_range_params[12].range_min_qp,
|
||||
RANGE_MAX_QP12, reg_vals->pps.rc_range_params[12].range_max_qp,
|
||||
RANGE_BPG_OFFSET12, reg_vals->pps.rc_range_params[12].range_bpg_offset);
|
||||
|
||||
REG_SET_6(DSCC_PPS_CONFIG22, 0,
|
||||
RANGE_MIN_QP13, reg_vals->pps.rc_range_params[13].range_min_qp,
|
||||
RANGE_MAX_QP13, reg_vals->pps.rc_range_params[13].range_max_qp,
|
||||
RANGE_BPG_OFFSET13, reg_vals->pps.rc_range_params[13].range_bpg_offset,
|
||||
RANGE_MIN_QP14, reg_vals->pps.rc_range_params[14].range_min_qp,
|
||||
RANGE_MAX_QP14, reg_vals->pps.rc_range_params[14].range_max_qp,
|
||||
RANGE_BPG_OFFSET14, reg_vals->pps.rc_range_params[14].range_bpg_offset);
|
||||
|
||||
if (IS_FPGA_MAXIMUS_DC(dsc20->base.ctx->dce_environment)) {
|
||||
/* It's safe to do this as long as debug bus is not being used in DAL Diag environment.
|
||||
*
|
||||
* This is because DSCC_PPS_CONFIG4.INITIAL_DEC_DELAY is a read-only register field (because it's a decoder
|
||||
* value not required by DSC encoder). However, since decoding fails when this value is missing from PPS, it's
|
||||
* required to communicate this value to the PPS header. When testing on FPGA, the values for PPS header are
|
||||
* being read from Diag register dump. The register below is used in place of a scratch register to make
|
||||
* 'initial_dec_delay' available.
|
||||
*/
|
||||
|
||||
temp_int = reg_vals->pps.initial_dec_delay;
|
||||
REG_SET_4(DSCC_TEST_DEBUG_BUS_ROTATE, 0,
|
||||
DSCC_TEST_DEBUG_BUS0_ROTATE, temp_int & 0x1f,
|
||||
DSCC_TEST_DEBUG_BUS1_ROTATE, temp_int >> 5 & 0x1f,
|
||||
DSCC_TEST_DEBUG_BUS2_ROTATE, temp_int >> 10 & 0x1f,
|
||||
DSCC_TEST_DEBUG_BUS3_ROTATE, temp_int >> 15 & 0x1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
573
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h
Normal file
573
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h
Normal file
@ -0,0 +1,573 @@
|
||||
/* Copyright 2017 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
|
||||
*
|
||||
*/
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
#ifndef __DCN20_DSC_H__
|
||||
#define __DCN20_DSC_H__
|
||||
|
||||
#include "dsc.h"
|
||||
#include "dsc/dscc_types.h"
|
||||
#include <drm/drm_dsc.h>
|
||||
|
||||
#define TO_DCN20_DSC(dsc)\
|
||||
container_of(dsc, struct dcn20_dsc, base)
|
||||
|
||||
#define DSC_REG_LIST_DCN20(id) \
|
||||
SRI(DSC_TOP_CONTROL, DSC_TOP, id),\
|
||||
SRI(DSC_DEBUG_CONTROL, DSC_TOP, id),\
|
||||
SRI(DSCC_CONFIG0, DSCC, id),\
|
||||
SRI(DSCC_CONFIG1, DSCC, id),\
|
||||
SRI(DSCC_STATUS, DSCC, id),\
|
||||
SRI(DSCC_INTERRUPT_CONTROL_STATUS, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG0, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG1, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG2, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG3, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG4, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG5, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG6, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG7, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG8, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG9, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG10, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG11, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG12, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG13, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG14, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG15, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG16, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG17, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG18, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG19, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG20, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG21, DSCC, id),\
|
||||
SRI(DSCC_PPS_CONFIG22, DSCC, id),\
|
||||
SRI(DSCC_MEM_POWER_CONTROL, DSCC, id),\
|
||||
SRI(DSCC_R_Y_SQUARED_ERROR_LOWER, DSCC, id),\
|
||||
SRI(DSCC_R_Y_SQUARED_ERROR_UPPER, DSCC, id),\
|
||||
SRI(DSCC_G_CB_SQUARED_ERROR_LOWER, DSCC, id),\
|
||||
SRI(DSCC_G_CB_SQUARED_ERROR_UPPER, DSCC, id),\
|
||||
SRI(DSCC_B_CR_SQUARED_ERROR_LOWER, DSCC, id),\
|
||||
SRI(DSCC_B_CR_SQUARED_ERROR_UPPER, DSCC, id),\
|
||||
SRI(DSCC_MAX_ABS_ERROR0, DSCC, id),\
|
||||
SRI(DSCC_MAX_ABS_ERROR1, DSCC, id),\
|
||||
SRI(DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL, DSCC, id),\
|
||||
SRI(DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL, DSCC, id),\
|
||||
SRI(DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL, DSCC, id),\
|
||||
SRI(DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id),\
|
||||
SRI(DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL, DSCC, id),\
|
||||
SRI(DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL, DSCC, id),\
|
||||
SRI(DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL, DSCC, id),\
|
||||
SRI(DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id),\
|
||||
SRI(DSCC_TEST_DEBUG_BUS_ROTATE, DSCC, id),\
|
||||
SRI(DSCCIF_CONFIG0, DSCCIF, id),\
|
||||
SRI(DSCCIF_CONFIG1, DSCCIF, id),\
|
||||
SRI(DSCRM_DSC_FORWARD_CONFIG, DSCRM, id)
|
||||
|
||||
|
||||
#define DSC_SF(reg_name, field_name, post_fix)\
|
||||
.field_name = reg_name ## __ ## field_name ## post_fix
|
||||
|
||||
//Used in resolving the corner case with duplicate field name
|
||||
#define DSC2_SF(reg_name, field_name, post_fix)\
|
||||
.field_name = reg_name ## _ ## field_name ## post_fix
|
||||
|
||||
#define DSC_REG_LIST_SH_MASK_DCN20(mask_sh)\
|
||||
DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_CLOCK_EN, mask_sh), \
|
||||
DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_DISPCLK_R_GATE_DIS, mask_sh), \
|
||||
DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_DSCCLK_R_GATE_DIS, mask_sh), \
|
||||
DSC_SF(DSC_TOP0_DSC_DEBUG_CONTROL, DSC_DBG_EN, mask_sh), \
|
||||
DSC_SF(DSC_TOP0_DSC_DEBUG_CONTROL, DSC_TEST_CLOCK_MUX_SEL, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_CONFIG0, ICH_RESET_AT_END_OF_LINE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_CONFIG0, NUMBER_OF_SLICES_PER_LINE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_CONFIG0, ALTERNATE_ICH_ENCODING_EN, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_CONFIG0, NUMBER_OF_SLICES_IN_VERTICAL_DIRECTION, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_CONFIG1, DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_CONFIG1, DSCC_DISABLE_ICH, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_STATUS, DSCC_DOUBLE_BUFFER_REG_UPDATE_PENDING, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_OVERFLOW_OCCURRED, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_OVERFLOW_OCCURRED, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_OVERFLOW_OCCURRED, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_OVERFLOW_OCCURRED, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_UNDERFLOW_OCCURRED, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_UNDERFLOW_OCCURRED, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_UNDERFLOW_OCCURRED, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_UNDERFLOW_OCCURRED, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG0, DSC_VERSION_MINOR, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG0, DSC_VERSION_MAJOR, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG0, PPS_IDENTIFIER, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG0, LINEBUF_DEPTH, mask_sh), \
|
||||
DSC2_SF(DSCC0, DSCC_PPS_CONFIG0__BITS_PER_COMPONENT, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG1, BITS_PER_PIXEL, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG1, VBR_ENABLE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG1, SIMPLE_422, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG1, CONVERT_RGB, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG1, BLOCK_PRED_ENABLE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG1, NATIVE_422, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG1, NATIVE_420, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG1, CHUNK_SIZE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG2, PIC_WIDTH, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG2, PIC_HEIGHT, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG3, SLICE_WIDTH, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG3, SLICE_HEIGHT, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG4, INITIAL_XMIT_DELAY, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG4, INITIAL_DEC_DELAY, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG5, INITIAL_SCALE_VALUE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG5, SCALE_INCREMENT_INTERVAL, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG6, SCALE_DECREMENT_INTERVAL, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG6, FIRST_LINE_BPG_OFFSET, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG6, SECOND_LINE_BPG_OFFSET, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG7, NFL_BPG_OFFSET, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG7, SLICE_BPG_OFFSET, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG8, NSL_BPG_OFFSET, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG8, SECOND_LINE_OFFSET_ADJ, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG9, INITIAL_OFFSET, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG9, FINAL_OFFSET, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG10, FLATNESS_MIN_QP, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG10, FLATNESS_MAX_QP, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG10, RC_MODEL_SIZE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_EDGE_FACTOR, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_QUANT_INCR_LIMIT0, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_QUANT_INCR_LIMIT1, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_TGT_OFFSET_LO, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_TGT_OFFSET_HI, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH0, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH1, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH2, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH3, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH4, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH5, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH6, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH7, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH8, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH9, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH10, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH11, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RC_BUF_THRESH12, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RC_BUF_THRESH13, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RANGE_MIN_QP0, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RANGE_MAX_QP0, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RANGE_BPG_OFFSET0, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MIN_QP1, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MAX_QP1, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_BPG_OFFSET1, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MIN_QP2, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MAX_QP2, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_BPG_OFFSET2, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MIN_QP3, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MAX_QP3, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_BPG_OFFSET3, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MIN_QP4, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MAX_QP4, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_BPG_OFFSET4, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MIN_QP5, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MAX_QP5, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_BPG_OFFSET5, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MIN_QP6, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MAX_QP6, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_BPG_OFFSET6, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MIN_QP7, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MAX_QP7, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_BPG_OFFSET7, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MIN_QP8, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MAX_QP8, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_BPG_OFFSET8, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MIN_QP9, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MAX_QP9, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_BPG_OFFSET9, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MIN_QP10, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MAX_QP10, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_BPG_OFFSET10, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MIN_QP11, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MAX_QP11, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_BPG_OFFSET11, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MIN_QP12, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MAX_QP12, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_BPG_OFFSET12, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MIN_QP13, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MAX_QP13, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_BPG_OFFSET13, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MIN_QP14, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MAX_QP14, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_BPG_OFFSET14, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_DEFAULT_MEM_LOW_POWER_STATE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_MEM_PWR_FORCE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_MEM_PWR_DIS, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_MEM_PWR_STATE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_NATIVE_422_MEM_PWR_FORCE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_NATIVE_422_MEM_PWR_DIS, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_NATIVE_422_MEM_PWR_STATE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_R_Y_SQUARED_ERROR_LOWER, DSCC_R_Y_SQUARED_ERROR_LOWER, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_R_Y_SQUARED_ERROR_UPPER, DSCC_R_Y_SQUARED_ERROR_UPPER, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_G_CB_SQUARED_ERROR_LOWER, DSCC_G_CB_SQUARED_ERROR_LOWER, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_G_CB_SQUARED_ERROR_UPPER, DSCC_G_CB_SQUARED_ERROR_UPPER, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_B_CR_SQUARED_ERROR_LOWER, DSCC_B_CR_SQUARED_ERROR_LOWER, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_B_CR_SQUARED_ERROR_UPPER, DSCC_B_CR_SQUARED_ERROR_UPPER, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_MAX_ABS_ERROR0, DSCC_R_Y_MAX_ABS_ERROR, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_MAX_ABS_ERROR0, DSCC_G_CB_MAX_ABS_ERROR, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_MAX_ABS_ERROR1, DSCC_B_CR_MAX_ABS_ERROR, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE, DSCC_TEST_DEBUG_BUS0_ROTATE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE, DSCC_TEST_DEBUG_BUS1_ROTATE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE, DSCC_TEST_DEBUG_BUS2_ROTATE, mask_sh), \
|
||||
DSC_SF(DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE, DSCC_TEST_DEBUG_BUS3_ROTATE, mask_sh), \
|
||||
DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_INTERFACE_UNDERFLOW_RECOVERY_EN, mask_sh), \
|
||||
DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_INTERFACE_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \
|
||||
DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_INTERFACE_UNDERFLOW_OCCURRED_STATUS, mask_sh), \
|
||||
DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_PIXEL_FORMAT, mask_sh), \
|
||||
DSC2_SF(DSCCIF0, DSCCIF_CONFIG0__BITS_PER_COMPONENT, mask_sh), \
|
||||
DSC_SF(DSCCIF0_DSCCIF_CONFIG0, DOUBLE_BUFFER_REG_UPDATE_PENDING, mask_sh), \
|
||||
DSC_SF(DSCCIF0_DSCCIF_CONFIG1, PIC_WIDTH, mask_sh), \
|
||||
DSC_SF(DSCCIF0_DSCCIF_CONFIG1, PIC_HEIGHT, mask_sh), \
|
||||
DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, mask_sh), \
|
||||
DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_OPP_PIPE_SOURCE, mask_sh)
|
||||
|
||||
|
||||
|
||||
#define DSC_FIELD_LIST_DCN20(type)\
|
||||
type DSC_CLOCK_EN; \
|
||||
type DSC_DISPCLK_R_GATE_DIS; \
|
||||
type DSC_DSCCLK_R_GATE_DIS; \
|
||||
type DSC_DBG_EN; \
|
||||
type DSC_TEST_CLOCK_MUX_SEL; \
|
||||
type ICH_RESET_AT_END_OF_LINE; \
|
||||
type NUMBER_OF_SLICES_PER_LINE; \
|
||||
type ALTERNATE_ICH_ENCODING_EN; \
|
||||
type NUMBER_OF_SLICES_IN_VERTICAL_DIRECTION; \
|
||||
type DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE; \
|
||||
type DSCC_DISABLE_ICH; \
|
||||
type DSCC_DOUBLE_BUFFER_REG_UPDATE_PENDING; \
|
||||
type DSCC_RATE_BUFFER0_OVERFLOW_OCCURRED; \
|
||||
type DSCC_RATE_BUFFER1_OVERFLOW_OCCURRED; \
|
||||
type DSCC_RATE_BUFFER2_OVERFLOW_OCCURRED; \
|
||||
type DSCC_RATE_BUFFER3_OVERFLOW_OCCURRED; \
|
||||
type DSCC_RATE_BUFFER0_UNDERFLOW_OCCURRED; \
|
||||
type DSCC_RATE_BUFFER1_UNDERFLOW_OCCURRED; \
|
||||
type DSCC_RATE_BUFFER2_UNDERFLOW_OCCURRED; \
|
||||
type DSCC_RATE_BUFFER3_UNDERFLOW_OCCURRED; \
|
||||
type DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED; \
|
||||
type DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED; \
|
||||
type DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED; \
|
||||
type DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED; \
|
||||
type DSCC_RATE_BUFFER0_OVERFLOW_OCCURRED_INT_EN; \
|
||||
type DSCC_RATE_BUFFER1_OVERFLOW_OCCURRED_INT_EN; \
|
||||
type DSCC_RATE_BUFFER2_OVERFLOW_OCCURRED_INT_EN; \
|
||||
type DSCC_RATE_BUFFER3_OVERFLOW_OCCURRED_INT_EN; \
|
||||
type DSCC_RATE_BUFFER0_UNDERFLOW_OCCURRED_INT_EN; \
|
||||
type DSCC_RATE_BUFFER1_UNDERFLOW_OCCURRED_INT_EN; \
|
||||
type DSCC_RATE_BUFFER2_UNDERFLOW_OCCURRED_INT_EN; \
|
||||
type DSCC_RATE_BUFFER3_UNDERFLOW_OCCURRED_INT_EN; \
|
||||
type DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED_INT_EN; \
|
||||
type DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED_INT_EN; \
|
||||
type DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED_INT_EN; \
|
||||
type DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED_INT_EN; \
|
||||
type DSC_VERSION_MINOR; \
|
||||
type DSC_VERSION_MAJOR; \
|
||||
type PPS_IDENTIFIER; \
|
||||
type LINEBUF_DEPTH; \
|
||||
type DSCC_PPS_CONFIG0__BITS_PER_COMPONENT; \
|
||||
type BITS_PER_PIXEL; \
|
||||
type VBR_ENABLE; \
|
||||
type SIMPLE_422; \
|
||||
type CONVERT_RGB; \
|
||||
type BLOCK_PRED_ENABLE; \
|
||||
type NATIVE_422; \
|
||||
type NATIVE_420; \
|
||||
type CHUNK_SIZE; \
|
||||
type PIC_WIDTH; \
|
||||
type PIC_HEIGHT; \
|
||||
type SLICE_WIDTH; \
|
||||
type SLICE_HEIGHT; \
|
||||
type INITIAL_XMIT_DELAY; \
|
||||
type INITIAL_DEC_DELAY; \
|
||||
type INITIAL_SCALE_VALUE; \
|
||||
type SCALE_INCREMENT_INTERVAL; \
|
||||
type SCALE_DECREMENT_INTERVAL; \
|
||||
type FIRST_LINE_BPG_OFFSET; \
|
||||
type SECOND_LINE_BPG_OFFSET; \
|
||||
type NFL_BPG_OFFSET; \
|
||||
type SLICE_BPG_OFFSET; \
|
||||
type NSL_BPG_OFFSET; \
|
||||
type SECOND_LINE_OFFSET_ADJ; \
|
||||
type INITIAL_OFFSET; \
|
||||
type FINAL_OFFSET; \
|
||||
type FLATNESS_MIN_QP; \
|
||||
type FLATNESS_MAX_QP; \
|
||||
type RC_MODEL_SIZE; \
|
||||
type RC_EDGE_FACTOR; \
|
||||
type RC_QUANT_INCR_LIMIT0; \
|
||||
type RC_QUANT_INCR_LIMIT1; \
|
||||
type RC_TGT_OFFSET_LO; \
|
||||
type RC_TGT_OFFSET_HI; \
|
||||
type RC_BUF_THRESH0; \
|
||||
type RC_BUF_THRESH1; \
|
||||
type RC_BUF_THRESH2; \
|
||||
type RC_BUF_THRESH3; \
|
||||
type RC_BUF_THRESH4; \
|
||||
type RC_BUF_THRESH5; \
|
||||
type RC_BUF_THRESH6; \
|
||||
type RC_BUF_THRESH7; \
|
||||
type RC_BUF_THRESH8; \
|
||||
type RC_BUF_THRESH9; \
|
||||
type RC_BUF_THRESH10; \
|
||||
type RC_BUF_THRESH11; \
|
||||
type RC_BUF_THRESH12; \
|
||||
type RC_BUF_THRESH13; \
|
||||
type RANGE_MIN_QP0; \
|
||||
type RANGE_MAX_QP0; \
|
||||
type RANGE_BPG_OFFSET0; \
|
||||
type RANGE_MIN_QP1; \
|
||||
type RANGE_MAX_QP1; \
|
||||
type RANGE_BPG_OFFSET1; \
|
||||
type RANGE_MIN_QP2; \
|
||||
type RANGE_MAX_QP2; \
|
||||
type RANGE_BPG_OFFSET2; \
|
||||
type RANGE_MIN_QP3; \
|
||||
type RANGE_MAX_QP3; \
|
||||
type RANGE_BPG_OFFSET3; \
|
||||
type RANGE_MIN_QP4; \
|
||||
type RANGE_MAX_QP4; \
|
||||
type RANGE_BPG_OFFSET4; \
|
||||
type RANGE_MIN_QP5; \
|
||||
type RANGE_MAX_QP5; \
|
||||
type RANGE_BPG_OFFSET5; \
|
||||
type RANGE_MIN_QP6; \
|
||||
type RANGE_MAX_QP6; \
|
||||
type RANGE_BPG_OFFSET6; \
|
||||
type RANGE_MIN_QP7; \
|
||||
type RANGE_MAX_QP7; \
|
||||
type RANGE_BPG_OFFSET7; \
|
||||
type RANGE_MIN_QP8; \
|
||||
type RANGE_MAX_QP8; \
|
||||
type RANGE_BPG_OFFSET8; \
|
||||
type RANGE_MIN_QP9; \
|
||||
type RANGE_MAX_QP9; \
|
||||
type RANGE_BPG_OFFSET9; \
|
||||
type RANGE_MIN_QP10; \
|
||||
type RANGE_MAX_QP10; \
|
||||
type RANGE_BPG_OFFSET10; \
|
||||
type RANGE_MIN_QP11; \
|
||||
type RANGE_MAX_QP11; \
|
||||
type RANGE_BPG_OFFSET11; \
|
||||
type RANGE_MIN_QP12; \
|
||||
type RANGE_MAX_QP12; \
|
||||
type RANGE_BPG_OFFSET12; \
|
||||
type RANGE_MIN_QP13; \
|
||||
type RANGE_MAX_QP13; \
|
||||
type RANGE_BPG_OFFSET13; \
|
||||
type RANGE_MIN_QP14; \
|
||||
type RANGE_MAX_QP14; \
|
||||
type RANGE_BPG_OFFSET14; \
|
||||
type DSCC_DEFAULT_MEM_LOW_POWER_STATE; \
|
||||
type DSCC_MEM_PWR_FORCE; \
|
||||
type DSCC_MEM_PWR_DIS; \
|
||||
type DSCC_MEM_PWR_STATE; \
|
||||
type DSCC_NATIVE_422_MEM_PWR_FORCE; \
|
||||
type DSCC_NATIVE_422_MEM_PWR_DIS; \
|
||||
type DSCC_NATIVE_422_MEM_PWR_STATE; \
|
||||
type DSCC_R_Y_SQUARED_ERROR_LOWER; \
|
||||
type DSCC_R_Y_SQUARED_ERROR_UPPER; \
|
||||
type DSCC_G_CB_SQUARED_ERROR_LOWER; \
|
||||
type DSCC_G_CB_SQUARED_ERROR_UPPER; \
|
||||
type DSCC_B_CR_SQUARED_ERROR_LOWER; \
|
||||
type DSCC_B_CR_SQUARED_ERROR_UPPER; \
|
||||
type DSCC_R_Y_MAX_ABS_ERROR; \
|
||||
type DSCC_G_CB_MAX_ABS_ERROR; \
|
||||
type DSCC_B_CR_MAX_ABS_ERROR; \
|
||||
type DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL; \
|
||||
type DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL; \
|
||||
type DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL; \
|
||||
type DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL; \
|
||||
type DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL; \
|
||||
type DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL; \
|
||||
type DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL; \
|
||||
type DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL; \
|
||||
type DSCC_UPDATE_PENDING_STATUS; \
|
||||
type DSCC_UPDATE_TAKEN_STATUS; \
|
||||
type DSCC_UPDATE_TAKEN_ACK; \
|
||||
type DSCC_TEST_DEBUG_BUS0_ROTATE; \
|
||||
type DSCC_TEST_DEBUG_BUS1_ROTATE; \
|
||||
type DSCC_TEST_DEBUG_BUS2_ROTATE; \
|
||||
type DSCC_TEST_DEBUG_BUS3_ROTATE; \
|
||||
type DSCC_RATE_BUFFER0_FULLNESS_LEVEL; \
|
||||
type DSCC_RATE_BUFFER1_FULLNESS_LEVEL; \
|
||||
type DSCC_RATE_BUFFER2_FULLNESS_LEVEL; \
|
||||
type DSCC_RATE_BUFFER3_FULLNESS_LEVEL; \
|
||||
type DSCC_RATE_CONTROL_BUFFER0_FULLNESS_LEVEL; \
|
||||
type DSCC_RATE_CONTROL_BUFFER1_FULLNESS_LEVEL; \
|
||||
type DSCC_RATE_CONTROL_BUFFER2_FULLNESS_LEVEL; \
|
||||
type DSCC_RATE_CONTROL_BUFFER3_FULLNESS_LEVEL; \
|
||||
type DSCC_RATE_BUFFER0_INITIAL_XMIT_DELAY_REACHED; \
|
||||
type DSCC_RATE_BUFFER1_INITIAL_XMIT_DELAY_REACHED; \
|
||||
type DSCC_RATE_BUFFER2_INITIAL_XMIT_DELAY_REACHED; \
|
||||
type DSCC_RATE_BUFFER3_INITIAL_XMIT_DELAY_REACHED; \
|
||||
type INPUT_INTERFACE_UNDERFLOW_RECOVERY_EN; \
|
||||
type INPUT_INTERFACE_UNDERFLOW_OCCURRED_INT_EN; \
|
||||
type INPUT_INTERFACE_UNDERFLOW_OCCURRED_STATUS; \
|
||||
type INPUT_PIXEL_FORMAT; \
|
||||
type DSCCIF_CONFIG0__BITS_PER_COMPONENT; \
|
||||
type DOUBLE_BUFFER_REG_UPDATE_PENDING; \
|
||||
type DSCCIF_UPDATE_PENDING_STATUS; \
|
||||
type DSCCIF_UPDATE_TAKEN_STATUS; \
|
||||
type DSCCIF_UPDATE_TAKEN_ACK; \
|
||||
type DSCRM_DSC_FORWARD_EN; \
|
||||
type DSCRM_DSC_OPP_PIPE_SOURCE
|
||||
|
||||
|
||||
struct dcn20_dsc_registers {
|
||||
uint32_t DSC_TOP_CONTROL;
|
||||
uint32_t DSC_DEBUG_CONTROL;
|
||||
uint32_t DSCC_CONFIG0;
|
||||
uint32_t DSCC_CONFIG1;
|
||||
uint32_t DSCC_STATUS;
|
||||
uint32_t DSCC_INTERRUPT_CONTROL_STATUS;
|
||||
uint32_t DSCC_PPS_CONFIG0;
|
||||
uint32_t DSCC_PPS_CONFIG1;
|
||||
uint32_t DSCC_PPS_CONFIG2;
|
||||
uint32_t DSCC_PPS_CONFIG3;
|
||||
uint32_t DSCC_PPS_CONFIG4;
|
||||
uint32_t DSCC_PPS_CONFIG5;
|
||||
uint32_t DSCC_PPS_CONFIG6;
|
||||
uint32_t DSCC_PPS_CONFIG7;
|
||||
uint32_t DSCC_PPS_CONFIG8;
|
||||
uint32_t DSCC_PPS_CONFIG9;
|
||||
uint32_t DSCC_PPS_CONFIG10;
|
||||
uint32_t DSCC_PPS_CONFIG11;
|
||||
uint32_t DSCC_PPS_CONFIG12;
|
||||
uint32_t DSCC_PPS_CONFIG13;
|
||||
uint32_t DSCC_PPS_CONFIG14;
|
||||
uint32_t DSCC_PPS_CONFIG15;
|
||||
uint32_t DSCC_PPS_CONFIG16;
|
||||
uint32_t DSCC_PPS_CONFIG17;
|
||||
uint32_t DSCC_PPS_CONFIG18;
|
||||
uint32_t DSCC_PPS_CONFIG19;
|
||||
uint32_t DSCC_PPS_CONFIG20;
|
||||
uint32_t DSCC_PPS_CONFIG21;
|
||||
uint32_t DSCC_PPS_CONFIG22;
|
||||
uint32_t DSCC_MEM_POWER_CONTROL;
|
||||
uint32_t DSCC_R_Y_SQUARED_ERROR_LOWER;
|
||||
uint32_t DSCC_R_Y_SQUARED_ERROR_UPPER;
|
||||
uint32_t DSCC_G_CB_SQUARED_ERROR_LOWER;
|
||||
uint32_t DSCC_G_CB_SQUARED_ERROR_UPPER;
|
||||
uint32_t DSCC_B_CR_SQUARED_ERROR_LOWER;
|
||||
uint32_t DSCC_B_CR_SQUARED_ERROR_UPPER;
|
||||
uint32_t DSCC_MAX_ABS_ERROR0;
|
||||
uint32_t DSCC_MAX_ABS_ERROR1;
|
||||
uint32_t DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL;
|
||||
uint32_t DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL;
|
||||
uint32_t DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL;
|
||||
uint32_t DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL;
|
||||
uint32_t DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL;
|
||||
uint32_t DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL;
|
||||
uint32_t DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL;
|
||||
uint32_t DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL;
|
||||
uint32_t DSCC_TEST_DEBUG_BUS_ROTATE;
|
||||
uint32_t DSCCIF_CONFIG0;
|
||||
uint32_t DSCCIF_CONFIG1;
|
||||
uint32_t DSCRM_DSC_FORWARD_CONFIG;
|
||||
};
|
||||
|
||||
|
||||
struct dcn20_dsc_shift {
|
||||
DSC_FIELD_LIST_DCN20(uint8_t);
|
||||
};
|
||||
|
||||
struct dcn20_dsc_mask {
|
||||
DSC_FIELD_LIST_DCN20(uint32_t);
|
||||
};
|
||||
|
||||
/* DSCCIF_CONFIG.INPUT_PIXEL_FORMAT values */
|
||||
enum dsc_pixel_format {
|
||||
DSC_PIXFMT_RGB,
|
||||
DSC_PIXFMT_YCBCR444,
|
||||
DSC_PIXFMT_SIMPLE_YCBCR422,
|
||||
DSC_PIXFMT_NATIVE_YCBCR422,
|
||||
DSC_PIXFMT_NATIVE_YCBCR420,
|
||||
DSC_PIXFMT_UNKNOWN
|
||||
};
|
||||
|
||||
struct dsc_reg_values {
|
||||
/* PPS registers */
|
||||
struct drm_dsc_config pps;
|
||||
|
||||
/* Additional registers */
|
||||
uint32_t dsc_clock_enable;
|
||||
uint32_t dsc_clock_gating_disable;
|
||||
uint32_t underflow_recovery_en;
|
||||
uint32_t underflow_occurred_int_en;
|
||||
uint32_t underflow_occurred_status;
|
||||
enum dsc_pixel_format pixel_format;
|
||||
uint32_t ich_reset_at_eol;
|
||||
uint32_t alternate_ich_encoding_en;
|
||||
uint32_t num_slices_h;
|
||||
uint32_t num_slices_v;
|
||||
uint32_t rc_buffer_model_size;
|
||||
uint32_t disable_ich;
|
||||
uint32_t bpp_x32;
|
||||
uint32_t dsc_dbg_en;
|
||||
uint32_t rc_buffer_model_overflow_int_en[4];
|
||||
};
|
||||
|
||||
struct dcn20_dsc {
|
||||
struct display_stream_compressor base;
|
||||
const struct dcn20_dsc_registers *dsc_regs;
|
||||
const struct dcn20_dsc_shift *dsc_shift;
|
||||
const struct dcn20_dsc_mask *dsc_mask;
|
||||
|
||||
struct dsc_reg_values reg_vals;
|
||||
};
|
||||
|
||||
|
||||
void dsc2_construct(struct dcn20_dsc *dsc,
|
||||
struct dc_context *ctx,
|
||||
int inst,
|
||||
const struct dcn20_dsc_registers *dsc_regs,
|
||||
const struct dcn20_dsc_shift *dsc_shift,
|
||||
const struct dcn20_dsc_mask *dsc_mask);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -32,6 +32,9 @@
|
||||
#include "dcn10/dcn10_hw_sequencer.h"
|
||||
#include "dcn20_hwseq.h"
|
||||
#include "dce/dce_hwseq.h"
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
#include "dcn20/dcn20_dsc.h"
|
||||
#endif
|
||||
#include "abm.h"
|
||||
#include "clk_mgr.h"
|
||||
#include "dmcu.h"
|
||||
@ -211,6 +214,76 @@ static void dcn20_init_blank(
|
||||
dcn20_hwss_wait_for_blank_complete(opp);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
static void dcn20_dsc_pg_control(
|
||||
struct dce_hwseq *hws,
|
||||
unsigned int dsc_inst,
|
||||
bool power_on)
|
||||
{
|
||||
uint32_t power_gate = power_on ? 0 : 1;
|
||||
uint32_t pwr_status = power_on ? 0 : 2;
|
||||
|
||||
if (hws->ctx->dc->debug.disable_dsc_power_gate)
|
||||
return;
|
||||
|
||||
if (REG(DOMAIN16_PG_CONFIG) == 0)
|
||||
return;
|
||||
|
||||
switch (dsc_inst) {
|
||||
case 0: /* DSC0 */
|
||||
REG_UPDATE(DOMAIN16_PG_CONFIG,
|
||||
DOMAIN16_POWER_GATE, power_gate);
|
||||
|
||||
REG_WAIT(DOMAIN16_PG_STATUS,
|
||||
DOMAIN16_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
break;
|
||||
case 1: /* DSC1 */
|
||||
REG_UPDATE(DOMAIN17_PG_CONFIG,
|
||||
DOMAIN17_POWER_GATE, power_gate);
|
||||
|
||||
REG_WAIT(DOMAIN17_PG_STATUS,
|
||||
DOMAIN17_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
break;
|
||||
case 2: /* DSC2 */
|
||||
REG_UPDATE(DOMAIN18_PG_CONFIG,
|
||||
DOMAIN18_POWER_GATE, power_gate);
|
||||
|
||||
REG_WAIT(DOMAIN18_PG_STATUS,
|
||||
DOMAIN18_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
break;
|
||||
case 3: /* DSC3 */
|
||||
REG_UPDATE(DOMAIN19_PG_CONFIG,
|
||||
DOMAIN19_POWER_GATE, power_gate);
|
||||
|
||||
REG_WAIT(DOMAIN19_PG_STATUS,
|
||||
DOMAIN19_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
break;
|
||||
case 4: /* DSC4 */
|
||||
REG_UPDATE(DOMAIN20_PG_CONFIG,
|
||||
DOMAIN20_POWER_GATE, power_gate);
|
||||
|
||||
REG_WAIT(DOMAIN20_PG_STATUS,
|
||||
DOMAIN20_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
break;
|
||||
case 5: /* DSC5 */
|
||||
REG_UPDATE(DOMAIN21_PG_CONFIG,
|
||||
DOMAIN21_POWER_GATE, power_gate);
|
||||
|
||||
REG_WAIT(DOMAIN21_PG_STATUS,
|
||||
DOMAIN21_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void dcn20_dpp_pg_control(
|
||||
struct dce_hwseq *hws,
|
||||
@ -1457,10 +1530,30 @@ bool dcn20_dmdata_status_done(struct pipe_ctx *pipe_ctx)
|
||||
|
||||
static void dcn20_disable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
struct dce_hwseq *hws = dc->hwseq;
|
||||
struct pipe_ctx *bot_odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
|
||||
|
||||
if (pipe_ctx->stream_res.dsc) {
|
||||
dcn20_dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, true);
|
||||
if (bot_odm_pipe)
|
||||
dcn20_dsc_pg_control(hws, bot_odm_pipe->stream_res.dsc->inst, true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void dcn20_enable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
struct dce_hwseq *hws = dc->hwseq;
|
||||
struct pipe_ctx *bot_odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
|
||||
|
||||
if (pipe_ctx->stream_res.dsc) {
|
||||
dcn20_dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, false);
|
||||
if (bot_odm_pipe)
|
||||
dcn20_dsc_pg_control(hws, bot_odm_pipe->stream_res.dsc->inst, false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void dcn20_set_dmdata_attributes(struct pipe_ctx *pipe_ctx)
|
||||
|
@ -168,6 +168,10 @@ static struct mpll_cfg dcn2_mpll_cfg[] = {
|
||||
void enc2_fec_set_enable(struct link_encoder *enc, bool enable)
|
||||
{
|
||||
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
DC_LOG_DSC("%s FEC at link encoder inst %d",
|
||||
enable ? "Enabling" : "Disabling", enc->id.enum_id);
|
||||
#endif
|
||||
REG_UPDATE(DP_DPHY_CNTL, DPHY_FEC_EN, enable);
|
||||
}
|
||||
|
||||
@ -188,6 +192,19 @@ bool enc2_fec_is_active(struct link_encoder *enc)
|
||||
return (active != 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
/* this function reads dsc related register fields to be logged later in dcn10_log_hw_state
|
||||
* into a dcn_dsc_state struct.
|
||||
*/
|
||||
void link_enc2_read_state(struct link_encoder *enc, struct link_enc_state *s)
|
||||
{
|
||||
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
|
||||
|
||||
REG_GET(DP_DPHY_CNTL, DPHY_FEC_EN, &s->dphy_fec_en);
|
||||
REG_GET(DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, &s->dphy_fec_ready_shadow);
|
||||
REG_GET(DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, &s->dphy_fec_active_status);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool update_cfg_data(
|
||||
struct dcn10_link_encoder *enc10,
|
||||
@ -298,6 +315,9 @@ void enc2_hw_init(struct link_encoder *enc)
|
||||
}
|
||||
|
||||
static const struct link_encoder_funcs dcn20_link_enc_funcs = {
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
.read_state = link_enc2_read_state,
|
||||
#endif
|
||||
.validate_output_with_stream =
|
||||
dcn10_link_encoder_validate_output_with_stream,
|
||||
.hw_init = enc2_hw_init,
|
||||
|
@ -151,6 +151,9 @@ void enc2_fec_set_ready(struct link_encoder *enc, bool ready);
|
||||
bool enc2_fec_is_active(struct link_encoder *enc);
|
||||
void enc2_hw_init(struct link_encoder *enc);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
void link_enc2_read_state(struct link_encoder *enc, struct link_enc_state *s);
|
||||
#endif
|
||||
|
||||
void dcn20_link_encoder_construct(
|
||||
struct dcn20_link_encoder *enc20,
|
||||
|
@ -167,6 +167,41 @@ void optc2_set_gsl_source_select(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
/* DSC encoder frame start controls: x = h position, line_num = # of lines from vstartup */
|
||||
void optc2_set_dsc_encoder_frame_start(struct timing_generator *optc,
|
||||
int x_position,
|
||||
int line_num)
|
||||
{
|
||||
struct optc *optc1 = DCN10TG_FROM_TG(optc);
|
||||
|
||||
REG_SET_2(OTG_DSC_START_POSITION, 0,
|
||||
OTG_DSC_START_POSITION_X, x_position,
|
||||
OTG_DSC_START_POSITION_LINE_NUM, line_num);
|
||||
}
|
||||
|
||||
/* Set DSC-related configuration.
|
||||
* dsc_mode: 0 disables DSC, other values enable DSC in specified format
|
||||
* sc_bytes_per_pixel: Bytes per pixel in u3.28 format
|
||||
* dsc_slice_width: Slice width in pixels
|
||||
*/
|
||||
void optc2_set_dsc_config(struct timing_generator *optc,
|
||||
enum optc_dsc_mode dsc_mode,
|
||||
uint32_t dsc_bytes_per_pixel,
|
||||
uint32_t dsc_slice_width)
|
||||
{
|
||||
struct optc *optc1 = DCN10TG_FROM_TG(optc);
|
||||
|
||||
REG_UPDATE(OPTC_DATA_FORMAT_CONTROL,
|
||||
OPTC_DSC_MODE, dsc_mode);
|
||||
|
||||
REG_SET(OPTC_BYTES_PER_PIXEL, 0,
|
||||
OPTC_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel);
|
||||
|
||||
REG_UPDATE(OPTC_WIDTH_CONTROL,
|
||||
OPTC_DSC_SLICE_WIDTH, dsc_slice_width);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* PTI i think is already done somewhere else for 2ka
|
||||
@ -390,6 +425,9 @@ static struct timing_generator_funcs dcn20_tg_funcs = {
|
||||
.setup_global_swap_lock = NULL,
|
||||
.get_crc = optc1_get_crc,
|
||||
.configure_crc = optc1_configure_crc,
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
.set_dsc_config = optc2_set_dsc_config,
|
||||
#endif
|
||||
.set_dwb_source = optc2_set_dwb_source,
|
||||
.set_odm_bypass = optc2_set_odm_bypass,
|
||||
.set_odm_combine = optc2_set_odm_combine,
|
||||
|
@ -83,6 +83,12 @@ void optc2_set_gsl_source_select(struct timing_generator *optc,
|
||||
int group_idx,
|
||||
uint32_t gsl_ready_signal);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
void optc2_set_dsc_config(struct timing_generator *optc,
|
||||
enum optc_dsc_mode dsc_mode,
|
||||
uint32_t dsc_bytes_per_pixel,
|
||||
uint32_t dsc_slice_width);
|
||||
#endif
|
||||
|
||||
void optc2_set_odm_bypass(struct timing_generator *optc,
|
||||
const struct dc_crtc_timing *dc_crtc_timing);
|
||||
|
@ -42,6 +42,10 @@
|
||||
#include "dce110/dce110_hw_sequencer.h"
|
||||
#include "dcn20_opp.h"
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
#include "dcn20_dsc.h"
|
||||
#endif
|
||||
|
||||
#include "dcn20_link_encoder.h"
|
||||
#include "dcn20_stream_encoder.h"
|
||||
#include "dce/dce_clock_source.h"
|
||||
@ -83,7 +87,11 @@ struct _vcs_dpi_ip_params_st dcn2_0_ip = {
|
||||
.hostvm_max_page_table_levels = 4,
|
||||
.hostvm_cached_page_table_levels = 0,
|
||||
.pte_group_size_bytes = 2048,
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
.num_dsc = 6,
|
||||
#else
|
||||
.num_dsc = 0,
|
||||
#endif
|
||||
.rob_buffer_size_kbytes = 168,
|
||||
.det_buffer_size_kbytes = 164,
|
||||
.dpte_buffer_size_in_pte_reqs_luma = 84,
|
||||
@ -572,6 +580,29 @@ static const struct dcn20_vmid_mask vmid_masks = {
|
||||
DCN20_VMID_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
#define dsc_regsDCN20(id)\
|
||||
[id] = {\
|
||||
DSC_REG_LIST_DCN20(id)\
|
||||
}
|
||||
|
||||
static const struct dcn20_dsc_registers dsc_regs[] = {
|
||||
dsc_regsDCN20(0),
|
||||
dsc_regsDCN20(1),
|
||||
dsc_regsDCN20(2),
|
||||
dsc_regsDCN20(3),
|
||||
dsc_regsDCN20(4),
|
||||
dsc_regsDCN20(5)
|
||||
};
|
||||
|
||||
static const struct dcn20_dsc_shift dsc_shift = {
|
||||
DSC_REG_LIST_SH_MASK_DCN20(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn20_dsc_mask dsc_mask = {
|
||||
DSC_REG_LIST_SH_MASK_DCN20(_MASK)
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct dccg_registers dccg_regs = {
|
||||
DCCG_REG_LIST_DCN2()
|
||||
@ -595,6 +626,9 @@ static const struct resource_caps res_cap_nv10 = {
|
||||
.num_dwb = 1,
|
||||
.num_ddc = 6,
|
||||
.num_vmid = 16,
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
.num_dsc = 6,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct dc_plane_cap plane_cap = {
|
||||
@ -961,6 +995,30 @@ void dcn20_clock_source_destroy(struct clock_source **clk_src)
|
||||
*clk_src = NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
|
||||
struct display_stream_compressor *dcn20_dsc_create(
|
||||
struct dc_context *ctx, uint32_t inst)
|
||||
{
|
||||
struct dcn20_dsc *dsc =
|
||||
kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL);
|
||||
|
||||
if (!dsc) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask);
|
||||
return &dsc->base;
|
||||
}
|
||||
|
||||
void dcn20_dsc_destroy(struct display_stream_compressor **dsc)
|
||||
{
|
||||
kfree(container_of(*dsc, struct dcn20_dsc, base));
|
||||
*dsc = NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void destruct(struct dcn20_resource_pool *pool)
|
||||
{
|
||||
@ -973,6 +1031,12 @@ static void destruct(struct dcn20_resource_pool *pool)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
|
||||
if (pool->base.dscs[i] != NULL)
|
||||
dcn20_dsc_destroy(&pool->base.dscs[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pool->base.mpc != NULL) {
|
||||
kfree(TO_DCN20_MPC(pool->base.mpc));
|
||||
@ -1164,6 +1228,39 @@ enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
|
||||
static struct display_stream_compressor *acquire_dsc(struct resource_context *res_ctx,
|
||||
const struct resource_pool *pool)
|
||||
{
|
||||
int i;
|
||||
struct display_stream_compressor *dsc = NULL;
|
||||
|
||||
/* Find first free DSC */
|
||||
for (i = 0; i < pool->res_cap->num_dsc; i++)
|
||||
if (!res_ctx->is_dsc_acquired[i]) {
|
||||
dsc = pool->dscs[i];
|
||||
res_ctx->is_dsc_acquired[i] = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return dsc;
|
||||
}
|
||||
|
||||
static void release_dsc(struct resource_context *res_ctx,
|
||||
const struct resource_pool *pool,
|
||||
const struct display_stream_compressor *dsc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pool->res_cap->num_dsc; i++)
|
||||
if (pool->dscs[i] == dsc) {
|
||||
res_ctx->is_dsc_acquired[i] = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
enum dc_status dcn20_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream)
|
||||
{
|
||||
@ -1174,6 +1271,33 @@ enum dc_status dcn20_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx,
|
||||
if (result == DC_OK)
|
||||
result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
/* Get a DSC if required and available */
|
||||
if (result == DC_OK) {
|
||||
int i;
|
||||
const struct resource_pool *pool = dc->res_pool;
|
||||
bool is_add_dsc = true;
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe_ctx->stream != dc_stream)
|
||||
continue;
|
||||
|
||||
if (is_add_dsc) {
|
||||
pipe_ctx->stream_res.dsc = acquire_dsc(&new_ctx->res_ctx, pool);
|
||||
|
||||
/* The number of DSCs can be less than the number of pipes */
|
||||
if (!pipe_ctx->stream_res.dsc) {
|
||||
dm_output_to_console("No DSCs available\n");
|
||||
result = DC_NO_DSC_RESOURCE;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (result == DC_OK)
|
||||
result = dcn20_build_mapped_resource(dc, new_ctx, dc_stream);
|
||||
@ -1198,6 +1322,18 @@ enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_
|
||||
if (!pipe_ctx)
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
if (pipe_ctx->stream_res.dsc) {
|
||||
struct pipe_ctx *odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
|
||||
|
||||
release_dsc(&new_ctx->res_ctx, dc->res_pool, pipe_ctx->stream_res.dsc);
|
||||
pipe_ctx->stream_res.dsc = NULL;
|
||||
if (odm_pipe) {
|
||||
release_dsc(&new_ctx->res_ctx, dc->res_pool, odm_pipe->stream_res.dsc);
|
||||
odm_pipe->stream_res.dsc = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return DC_OK;
|
||||
}
|
||||
@ -1331,6 +1467,14 @@ static bool dcn20_split_stream_for_combine(
|
||||
sd->recout.x = 0;
|
||||
}
|
||||
secondary_pipe->stream_res.opp = pool->opps[secondary_pipe->pipe_idx];
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
if (is_add_dsc) {
|
||||
secondary_pipe->stream_res.dsc = acquire_dsc(res_ctx, pool);
|
||||
ASSERT(secondary_pipe->stream_res.dsc);
|
||||
if (secondary_pipe->stream_res.dsc == NULL)
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
ASSERT(primary_pipe->plane_state);
|
||||
resource_build_scaling_params(primary_pipe);
|
||||
@ -1410,6 +1554,11 @@ int dcn20_populate_dml_pipes_from_context(
|
||||
pipes[pipe_cnt].pipe.src.dcc = 0;
|
||||
pipes[pipe_cnt].pipe.src.vm = 0;*/
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
pipes[pipe_cnt].dout.dsc_enable = res_ctx->pipe_ctx[i].stream->timing.flags.DSC;
|
||||
/* todo: rotation?*/
|
||||
pipes[pipe_cnt].dout.dsc_slices = res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.num_slices_h;
|
||||
#endif
|
||||
if (res_ctx->pipe_ctx[i].stream->use_dynamic_meta) {
|
||||
pipes[pipe_cnt].pipe.src.dynamic_metadata_enable = true;
|
||||
/* 1/2 vblank */
|
||||
@ -1751,6 +1900,10 @@ bool dcn20_validate_bandwidth(struct dc *dc,
|
||||
hsplit_pipe->stream = NULL;
|
||||
hsplit_pipe->top_pipe = NULL;
|
||||
hsplit_pipe->bottom_pipe = NULL;
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
if (hsplit_pipe->stream_res.dsc && hsplit_pipe->stream_res.dsc != pipe->stream_res.dsc)
|
||||
release_dsc(&context->res_ctx, dc->res_pool, hsplit_pipe->stream_res.dsc);
|
||||
#endif
|
||||
/* Clear plane_res and stream_res */
|
||||
memset(&hsplit_pipe->plane_res, 0, sizeof(hsplit_pipe->plane_res));
|
||||
memset(&hsplit_pipe->stream_res, 0, sizeof(hsplit_pipe->stream_res));
|
||||
@ -1997,6 +2150,10 @@ bool dcn20_validate_bandwidth(struct dc *dc,
|
||||
context->bw_ctx.bw.dcn.clk.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
|
||||
context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz =
|
||||
pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
context->res_ctx.pipe_ctx[i].plane_res.bw.dscclk_khz =
|
||||
context->bw_ctx.dml.vba.DSCCLK_calculated[pipe_idx] * 1000;
|
||||
#endif
|
||||
context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest;
|
||||
pipe_idx++;
|
||||
}
|
||||
@ -2045,6 +2202,23 @@ enum dc_status dcn20_validate_global(struct dc *dc, struct dc_state *new_ctx)
|
||||
if (pipe_ctx->stream != stream)
|
||||
continue;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
if (stream->timing.flags.DSC) {
|
||||
if (pipe_ctx->stream_res.dsc != NULL) {
|
||||
struct dsc_config dsc_cfg;
|
||||
|
||||
dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
|
||||
dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
|
||||
dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
|
||||
dsc_cfg.color_depth = stream->timing.display_color_depth;
|
||||
dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
|
||||
|
||||
if (!pipe_ctx->stream_res.dsc->funcs->dsc_validate_stream(pipe_ctx->stream_res.dsc, &dsc_cfg))
|
||||
result = DC_FAIL_DSC_VALIDATE;
|
||||
} else
|
||||
result = DC_FAIL_DSC_VALIDATE; // DSC enabled for this stream, but no free DSCs available
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -2715,6 +2889,16 @@ static bool construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
|
||||
pool->base.dscs[i] = dcn20_dsc_create(ctx, i);
|
||||
if (pool->base.dscs[i] == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create display stream compressor %d!\n", i);
|
||||
goto create_fail;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!resource_construct(num_virtual_links, dc, &pool->base,
|
||||
(!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
|
||||
|
@ -203,7 +203,165 @@ static void enc2_stream_encoder_stop_hdmi_info_packets(
|
||||
HDMI_GENERIC7_LINE, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
struct dc_info_packet_128 {
|
||||
bool valid;
|
||||
uint8_t hb0;
|
||||
uint8_t hb1;
|
||||
uint8_t hb2;
|
||||
uint8_t hb3;
|
||||
uint8_t sb[128];
|
||||
};
|
||||
|
||||
/* Update GSP7 SDP 128 byte long */
|
||||
static void enc2_send_gsp7_128_info_packet(
|
||||
struct dcn10_stream_encoder *enc1,
|
||||
const struct dc_info_packet_128 *info_packet)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
/* TODOFPGA Figure out a proper number for max_retries polling for lock
|
||||
* use 50 for now.
|
||||
*/
|
||||
uint32_t max_retries = 50;
|
||||
const uint32_t *content = (const uint32_t *) &info_packet->sb[0];
|
||||
|
||||
ASSERT(info_packet->hb1 == DC_DP_INFOFRAME_TYPE_PPS);
|
||||
|
||||
/* Configure for PPS packet size (128 bytes) */
|
||||
REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP7_PPS, 1);
|
||||
|
||||
/* We need turn on clock before programming AFMT block*/
|
||||
REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1);
|
||||
|
||||
/* Poll dig_update_lock is not locked -> asic internal signal
|
||||
* assumes otg master lock will unlock it
|
||||
*/
|
||||
/*REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, 0, 10, max_retries);*/
|
||||
|
||||
/* Wait for HW/SW GSP memory access conflict to go away */
|
||||
REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT,
|
||||
0, 10, max_retries);
|
||||
|
||||
/* Clear HW/SW memory access conflict flag */
|
||||
REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1);
|
||||
|
||||
/* write generic packet header */
|
||||
REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, 7);
|
||||
REG_SET_4(AFMT_GENERIC_HDR, 0,
|
||||
AFMT_GENERIC_HB0, info_packet->hb0,
|
||||
AFMT_GENERIC_HB1, info_packet->hb1,
|
||||
AFMT_GENERIC_HB2, info_packet->hb2,
|
||||
AFMT_GENERIC_HB3, info_packet->hb3);
|
||||
|
||||
/* Write generic packet content 128 bytes long. Four sets are used (indexes 7
|
||||
* through 10) to fit 128 bytes.
|
||||
*/
|
||||
for (i = 0; i < 4; i++) {
|
||||
uint32_t packet_index = 7 + i;
|
||||
REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, packet_index);
|
||||
|
||||
REG_WRITE(AFMT_GENERIC_0, *content++);
|
||||
REG_WRITE(AFMT_GENERIC_1, *content++);
|
||||
REG_WRITE(AFMT_GENERIC_2, *content++);
|
||||
REG_WRITE(AFMT_GENERIC_3, *content++);
|
||||
REG_WRITE(AFMT_GENERIC_4, *content++);
|
||||
REG_WRITE(AFMT_GENERIC_5, *content++);
|
||||
REG_WRITE(AFMT_GENERIC_6, *content++);
|
||||
REG_WRITE(AFMT_GENERIC_7, *content++);
|
||||
}
|
||||
|
||||
REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE, 1);
|
||||
}
|
||||
|
||||
/* Set DSC-related configuration.
|
||||
* dsc_mode: 0 disables DSC, other values enable DSC in specified format
|
||||
* sc_bytes_per_pixel: Bytes per pixel in u3.28 format
|
||||
* dsc_slice_width: Slice width in pixels
|
||||
*/
|
||||
static void enc2_dp_set_dsc_config(struct stream_encoder *enc,
|
||||
enum optc_dsc_mode dsc_mode,
|
||||
uint32_t dsc_bytes_per_pixel,
|
||||
uint32_t dsc_slice_width,
|
||||
uint8_t *dsc_packed_pps)
|
||||
{
|
||||
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
|
||||
|
||||
REG_UPDATE_2(DP_DSC_CNTL,
|
||||
DP_DSC_MODE, dsc_mode,
|
||||
DP_DSC_SLICE_WIDTH, dsc_slice_width);
|
||||
|
||||
REG_SET(DP_DSC_BYTES_PER_PIXEL, 0,
|
||||
DP_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel);
|
||||
|
||||
if (dsc_mode != OPTC_DSC_DISABLED) {
|
||||
struct dc_info_packet_128 pps_sdp;
|
||||
|
||||
ASSERT(dsc_packed_pps);
|
||||
|
||||
/* Load PPS into infoframe (SDP) registers */
|
||||
pps_sdp.valid = true;
|
||||
pps_sdp.hb0 = 0;
|
||||
pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS;
|
||||
pps_sdp.hb2 = 127;
|
||||
pps_sdp.hb3 = 0;
|
||||
memcpy(&pps_sdp.sb[0], dsc_packed_pps, sizeof(pps_sdp.sb));
|
||||
enc2_send_gsp7_128_info_packet(enc1, &pps_sdp);
|
||||
|
||||
/* Enable Generic Stream Packet 7 (GSP) transmission */
|
||||
//REG_UPDATE(DP_SEC_CNTL,
|
||||
// DP_SEC_GSP7_ENABLE, 1);
|
||||
|
||||
/* SW should make sure VBID[6] update line number is bigger
|
||||
* than PPS transmit line number
|
||||
*/
|
||||
REG_UPDATE(DP_SEC_CNTL6,
|
||||
DP_SEC_GSP7_LINE_NUM, 2);
|
||||
REG_UPDATE_2(DP_MSA_VBID_MISC,
|
||||
DP_VBID6_LINE_REFERENCE, 0,
|
||||
DP_VBID6_LINE_NUM, 3);
|
||||
|
||||
/* Send PPS data at the line number specified above.
|
||||
* DP spec requires PPS to be sent only when it changes, however since
|
||||
* decoder has to be able to handle its change on every frame, we're
|
||||
* sending it always (i.e. on every frame) to reduce the chance it'd be
|
||||
* missed by decoder. If it turns out required to send PPS only when it
|
||||
* changes, we can use DP_SEC_GSP7_SEND register.
|
||||
*/
|
||||
REG_UPDATE_2(DP_SEC_CNTL,
|
||||
DP_SEC_GSP7_ENABLE, 1,
|
||||
DP_SEC_STREAM_ENABLE, 1);
|
||||
} else {
|
||||
/* Disable Generic Stream Packet 7 (GSP) transmission */
|
||||
REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, 0);
|
||||
REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP7_PPS, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
/* this function read dsc related register fields to be logged later in dcn10_log_hw_state
|
||||
* into a dcn_dsc_state struct.
|
||||
*/
|
||||
static void enc2_read_state(struct stream_encoder *enc, struct enc_state *s)
|
||||
{
|
||||
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
|
||||
|
||||
//if dsc is enabled, continue to read
|
||||
REG_GET(DP_DSC_CNTL, DP_DSC_MODE, &s->dsc_mode);
|
||||
if (s->dsc_mode) {
|
||||
REG_GET(DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, &s->dsc_slice_width);
|
||||
REG_GET(DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, &s->sec_gsp7_line_num);
|
||||
|
||||
REG_GET(DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, &s->sec_gsp7_line_num);
|
||||
REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, &s->vbid6_line_reference);
|
||||
REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, &s->vbid6_line_num);
|
||||
|
||||
REG_GET(DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, &s->sec_gsp7_enable);
|
||||
REG_GET(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, &s->sec_stream_enable);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set Dynamic Metadata-configuration.
|
||||
* enable_dme: TRUE: enables Dynamic Metadata Enfine, FALSE: disables DME
|
||||
@ -283,6 +441,10 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
|
||||
{
|
||||
bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
|
||||
&& !timing->dsc_cfg.ycbcr422_simple);
|
||||
#endif
|
||||
return two_pix;
|
||||
}
|
||||
|
||||
@ -416,7 +578,13 @@ static const struct stream_encoder_funcs dcn20_str_enc_funcs = {
|
||||
.setup_stereo_sync = enc1_setup_stereo_sync,
|
||||
.set_avmute = enc1_stream_encoder_set_avmute,
|
||||
.dig_connect_to_otg = enc1_dig_connect_to_otg,
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
.enc_read_state = enc2_read_state,
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
.dp_set_dsc_config = enc2_dp_set_dsc_config,
|
||||
#endif
|
||||
.set_dynamic_metadata = enc2_set_dynamic_metadata,
|
||||
};
|
||||
|
||||
|
@ -118,6 +118,13 @@ bool dm_helpers_submit_i2c(
|
||||
const struct dc_link *link,
|
||||
struct i2c_command *cmd);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
bool dm_helpers_dp_write_dsc_enable(
|
||||
struct dc_context *ctx,
|
||||
const struct dc_stream_state *stream,
|
||||
bool enable
|
||||
);
|
||||
#endif
|
||||
bool dm_helpers_is_dp_sink_present(
|
||||
struct dc_link *link);
|
||||
|
||||
|
13
drivers/gpu/drm/amd/display/dc/dsc/Makefile
Normal file
13
drivers/gpu/drm/amd/display/dc/dsc/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
#
|
||||
# Makefile for the 'dsc' sub-component of DAL.
|
||||
|
||||
CFLAGS_rc_calc.o := -mhard-float -msse -mpreferred-stack-boundary=4
|
||||
CFLAGS_rc_calc_dpi.o := -mhard-float -msse -mpreferred-stack-boundary=4
|
||||
CFLAGS_codec_main_amd.o := -mhard-float -msse -mpreferred-stack-boundary=4
|
||||
CFLAGS_dc_dsc.o := -mhard-float -msse -mpreferred-stack-boundary=4
|
||||
|
||||
DSC = dc_dsc.o rc_calc.o rc_calc_dpi.o
|
||||
|
||||
AMD_DAL_DSC = $(addprefix $(AMDDALPATH)/dc/dsc/,$(DSC))
|
||||
|
||||
AMD_DISPLAY_FILES += $(AMD_DAL_DSC)
|
899
drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
Normal file
899
drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
Normal file
@ -0,0 +1,899 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
*
|
||||
* Author: AMD
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
#include "dc.h"
|
||||
#include "core_types.h"
|
||||
#include "dsc.h"
|
||||
#include <drm/drm_dp_helper.h>
|
||||
|
||||
/* This module's internal functions */
|
||||
|
||||
static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size)
|
||||
{
|
||||
|
||||
switch (dpcd_buff_block_size) {
|
||||
case DP_DSC_RC_BUF_BLK_SIZE_1:
|
||||
*buff_block_size = 1024;
|
||||
break;
|
||||
case DP_DSC_RC_BUF_BLK_SIZE_4:
|
||||
*buff_block_size = 4 * 1024;
|
||||
break;
|
||||
case DP_DSC_RC_BUF_BLK_SIZE_16:
|
||||
*buff_block_size = 16 * 1024;
|
||||
break;
|
||||
case DP_DSC_RC_BUF_BLK_SIZE_64:
|
||||
*buff_block_size = 64 * 1024;
|
||||
break;
|
||||
default: {
|
||||
dm_error("%s: DPCD DSC buffer size not recoginzed.\n", __func__);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool dsc_line_buff_depth_from_dpcd(int dpcd_line_buff_bit_depth, int *line_buff_bit_depth)
|
||||
{
|
||||
if (0 <= dpcd_line_buff_bit_depth && dpcd_line_buff_bit_depth <= 7)
|
||||
*line_buff_bit_depth = dpcd_line_buff_bit_depth + 9;
|
||||
else if (dpcd_line_buff_bit_depth == 8)
|
||||
*line_buff_bit_depth = 8;
|
||||
else {
|
||||
dm_error("%s: DPCD DSC buffer depth not recoginzed.\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool dsc_throughput_from_dpcd(int dpcd_throughput, int *throughput)
|
||||
{
|
||||
switch (dpcd_throughput) {
|
||||
case DP_DSC_THROUGHPUT_MODE_0_340:
|
||||
*throughput = 340;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_400:
|
||||
*throughput = 400;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_450:
|
||||
*throughput = 450;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_500:
|
||||
*throughput = 500;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_550:
|
||||
*throughput = 550;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_600:
|
||||
*throughput = 600;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_650:
|
||||
*throughput = 650;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_700:
|
||||
*throughput = 700;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_750:
|
||||
*throughput = 750;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_800:
|
||||
*throughput = 800;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_850:
|
||||
*throughput = 850;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_900:
|
||||
*throughput = 900;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_950:
|
||||
*throughput = 950;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_1000:
|
||||
*throughput = 1000;
|
||||
break;
|
||||
default: {
|
||||
dm_error("%s: DPCD DSC througput mode not recoginzed.\n", __func__);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool dsc_bpp_increment_div_from_dpcd(int bpp_increment_dpcd, uint32_t *bpp_increment_div)
|
||||
{
|
||||
|
||||
switch (bpp_increment_dpcd) {
|
||||
case 0:
|
||||
*bpp_increment_div = 16;
|
||||
break;
|
||||
case 1:
|
||||
*bpp_increment_div = 8;
|
||||
break;
|
||||
case 2:
|
||||
*bpp_increment_div = 4;
|
||||
break;
|
||||
case 3:
|
||||
*bpp_increment_div = 2;
|
||||
break;
|
||||
case 4:
|
||||
*bpp_increment_div = 1;
|
||||
break;
|
||||
default: {
|
||||
dm_error("%s: DPCD DSC bits-per-pixel increment not recoginzed.\n", __func__);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void get_dsc_enc_caps(
|
||||
const struct dc *dc,
|
||||
struct dsc_enc_caps *dsc_enc_caps,
|
||||
int pixel_clock_100Hz)
|
||||
{
|
||||
// This is a static HW query, so we can use any DSC
|
||||
struct display_stream_compressor *dsc = dc->res_pool->dscs[0];
|
||||
|
||||
memset(dsc_enc_caps, 0, sizeof(struct dsc_enc_caps));
|
||||
if (dsc)
|
||||
dsc->funcs->dsc_get_enc_caps(dsc_enc_caps, pixel_clock_100Hz);
|
||||
}
|
||||
|
||||
/* Returns 'false' if no intersection was found for at least one capablity.
|
||||
* It also implicitly validates some sink caps against invalid value of zero.
|
||||
*/
|
||||
static bool dc_intersect_dsc_caps(
|
||||
const struct dsc_dec_dpcd_caps *dsc_sink_caps,
|
||||
const struct dsc_enc_caps *dsc_enc_caps,
|
||||
enum dc_pixel_encoding pixel_encoding,
|
||||
struct dsc_enc_caps *dsc_common_caps)
|
||||
{
|
||||
int32_t max_slices;
|
||||
int32_t total_sink_throughput;
|
||||
|
||||
memset(dsc_common_caps, 0, sizeof(struct dsc_enc_caps));
|
||||
|
||||
dsc_common_caps->dsc_version = min(dsc_sink_caps->dsc_version, dsc_enc_caps->dsc_version);
|
||||
if (!dsc_common_caps->dsc_version)
|
||||
return false;
|
||||
|
||||
dsc_common_caps->slice_caps.bits.NUM_SLICES_1 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_1 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_1;
|
||||
dsc_common_caps->slice_caps.bits.NUM_SLICES_2 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_2 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_2;
|
||||
dsc_common_caps->slice_caps.bits.NUM_SLICES_4 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_4 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_4;
|
||||
dsc_common_caps->slice_caps.bits.NUM_SLICES_8 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_8 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_8;
|
||||
if (!dsc_common_caps->slice_caps.raw)
|
||||
return false;
|
||||
|
||||
dsc_common_caps->lb_bit_depth = min(dsc_sink_caps->lb_bit_depth, dsc_enc_caps->lb_bit_depth);
|
||||
if (!dsc_common_caps->lb_bit_depth)
|
||||
return false;
|
||||
|
||||
dsc_common_caps->is_block_pred_supported = dsc_sink_caps->is_block_pred_supported && dsc_enc_caps->is_block_pred_supported;
|
||||
|
||||
dsc_common_caps->color_formats.raw = dsc_sink_caps->color_formats.raw & dsc_enc_caps->color_formats.raw;
|
||||
if (!dsc_common_caps->color_formats.raw)
|
||||
return false;
|
||||
|
||||
dsc_common_caps->color_depth.raw = dsc_sink_caps->color_depth.raw & dsc_enc_caps->color_depth.raw;
|
||||
if (!dsc_common_caps->color_depth.raw)
|
||||
return false;
|
||||
|
||||
max_slices = 0;
|
||||
if (dsc_common_caps->slice_caps.bits.NUM_SLICES_1)
|
||||
max_slices = 1;
|
||||
|
||||
if (dsc_common_caps->slice_caps.bits.NUM_SLICES_2)
|
||||
max_slices = 2;
|
||||
|
||||
if (dsc_common_caps->slice_caps.bits.NUM_SLICES_4)
|
||||
max_slices = 4;
|
||||
|
||||
total_sink_throughput = max_slices * dsc_sink_caps->throughput_mode_0_mps;
|
||||
if (pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420)
|
||||
total_sink_throughput = max_slices * dsc_sink_caps->throughput_mode_1_mps;
|
||||
|
||||
dsc_common_caps->max_total_throughput_mps = min(total_sink_throughput, dsc_enc_caps->max_total_throughput_mps);
|
||||
|
||||
dsc_common_caps->max_slice_width = min(dsc_sink_caps->max_slice_width, dsc_enc_caps->max_slice_width);
|
||||
if (!dsc_common_caps->max_slice_width)
|
||||
return false;
|
||||
|
||||
dsc_common_caps->bpp_increment_div = min(dsc_sink_caps->bpp_increment_div, dsc_enc_caps->bpp_increment_div);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO DSC: Can this be moved to a common helper module and replace WindowsDM::calcRequiredBandwidthForTiming()?
|
||||
static int bpp_from_dc_color_depth(enum dc_color_depth color_depth)
|
||||
{
|
||||
int bits_per_pixel;
|
||||
|
||||
// Get color depth in bits per pixel
|
||||
switch (color_depth) {
|
||||
case COLOR_DEPTH_UNDEFINED:
|
||||
bits_per_pixel = 0;
|
||||
break;
|
||||
case COLOR_DEPTH_666:
|
||||
bits_per_pixel = 6;
|
||||
break;
|
||||
case COLOR_DEPTH_888:
|
||||
bits_per_pixel = 8;
|
||||
break;
|
||||
case COLOR_DEPTH_101010:
|
||||
bits_per_pixel = 10;
|
||||
break;
|
||||
case COLOR_DEPTH_121212:
|
||||
bits_per_pixel = 12;
|
||||
break;
|
||||
case COLOR_DEPTH_141414:
|
||||
bits_per_pixel = 14;
|
||||
break;
|
||||
case COLOR_DEPTH_161616:
|
||||
bits_per_pixel = 16;
|
||||
break;
|
||||
case COLOR_DEPTH_999:
|
||||
bits_per_pixel = 9;
|
||||
break;
|
||||
case COLOR_DEPTH_111111:
|
||||
bits_per_pixel = 11;
|
||||
break;
|
||||
case COLOR_DEPTH_COUNT:
|
||||
default:
|
||||
bits_per_pixel = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return bits_per_pixel;
|
||||
}
|
||||
|
||||
// TODO DSC: Can this be moved to a common helper module and replace WindowsDM::calcRequiredBandwidthForTiming()?
|
||||
static int calc_required_bandwidth_for_timing(const struct dc_crtc_timing *crtc_timing)
|
||||
{
|
||||
int timing_bandwidth_kbps = 0;
|
||||
int bits_per_pixel = bpp_from_dc_color_depth(crtc_timing->display_color_depth);
|
||||
|
||||
if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB ||
|
||||
crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444)
|
||||
timing_bandwidth_kbps = crtc_timing->pix_clk_100hz * bits_per_pixel * 3 / 10;
|
||||
else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
|
||||
timing_bandwidth_kbps = crtc_timing->pix_clk_100hz * 8 * 3 / 10;
|
||||
else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
|
||||
timing_bandwidth_kbps = crtc_timing->pix_clk_100hz * bits_per_pixel * 3 / 20;
|
||||
|
||||
return timing_bandwidth_kbps;
|
||||
}
|
||||
|
||||
struct dc_dsc_policy {
|
||||
float max_compression_ratio_legacy;
|
||||
float sst_compression_legacy; // Maximum quality if 0.0
|
||||
float mst_compression_legacy;
|
||||
bool use_min_slices_h;
|
||||
int max_slices_h; // Maximum available if 0
|
||||
int num_slices_v;
|
||||
int max_target_bpp;
|
||||
int min_target_bpp; // Minimum target bits per pixel
|
||||
};
|
||||
|
||||
static inline uint32_t dsc_round_up(uint32_t value)
|
||||
{
|
||||
return (value + 9) / 10;
|
||||
}
|
||||
|
||||
static inline uint32_t calc_dsc_bpp_x16(uint32_t stream_bandwidth_kbps, uint32_t pix_clk_100hz, uint32_t bpp_increment_div)
|
||||
{
|
||||
uint32_t dsc_target_bpp_x16;
|
||||
float f_dsc_target_bpp;
|
||||
float f_stream_bandwidth_100bps = stream_bandwidth_kbps * 10.0f;
|
||||
uint32_t precision = bpp_increment_div; // bpp_increment_div is actually precision
|
||||
|
||||
f_dsc_target_bpp = f_stream_bandwidth_100bps / pix_clk_100hz;
|
||||
|
||||
// Round down to the nearest precision stop to bring it into DSC spec range
|
||||
dsc_target_bpp_x16 = (uint32_t)(f_dsc_target_bpp * precision);
|
||||
dsc_target_bpp_x16 = (dsc_target_bpp_x16 * 16) / precision;
|
||||
|
||||
return dsc_target_bpp_x16;
|
||||
}
|
||||
|
||||
const struct dc_dsc_policy dsc_policy = {
|
||||
.max_compression_ratio_legacy = 3.0f, // DSC Policy: Limit compression to 3:1 at most in all cases
|
||||
.sst_compression_legacy = 0.0f, // DSC Policy: SST - Maximum quality (0.0)
|
||||
.mst_compression_legacy = 3.0f, // DSC Policy: MST - always 3:1 compression
|
||||
.use_min_slices_h = true, // DSC Policy: Use minimum number of slices that fits the pixel clock
|
||||
.max_slices_h = 0, // DSC Policy: Use max available slices (in our case 4 for or 8, depending on the mode)
|
||||
|
||||
/* DSC Policy: Number of vertical slices set to 2 for no particular reason.
|
||||
* Seems small enough to not affect the quality too much, while still providing some error
|
||||
* propagation control (which may also help debugging).
|
||||
*/
|
||||
.num_slices_v = 16,
|
||||
.max_target_bpp = 24,
|
||||
.min_target_bpp = 8,
|
||||
};
|
||||
|
||||
static void get_dsc_bandwidth_range(
|
||||
const struct dc_dsc_policy *policy,
|
||||
const struct dsc_enc_caps *dsc_caps,
|
||||
const struct dc_crtc_timing *timing,
|
||||
struct dc_dsc_bw_range *range)
|
||||
{
|
||||
/* native stream bandwidth */
|
||||
range->stream_kbps = calc_required_bandwidth_for_timing(timing);
|
||||
|
||||
/* max dsc target bpp */
|
||||
range->max_kbps = dsc_round_up(policy->max_target_bpp * timing->pix_clk_100hz);
|
||||
range->max_target_bpp_x16 = policy->max_target_bpp * 16;
|
||||
if (range->max_kbps > range->stream_kbps) {
|
||||
/* max dsc target bpp is capped to native bandwidth */
|
||||
range->max_kbps = range->stream_kbps;
|
||||
range->max_target_bpp_x16 = calc_dsc_bpp_x16(range->stream_kbps, timing->pix_clk_100hz, dsc_caps->bpp_increment_div);
|
||||
}
|
||||
|
||||
/* min dsc target bpp */
|
||||
range->min_kbps = dsc_round_up(policy->min_target_bpp * timing->pix_clk_100hz);
|
||||
range->min_target_bpp_x16 = policy->min_target_bpp * 16;
|
||||
if (range->min_kbps > range->max_kbps) {
|
||||
/* min dsc target bpp is capped to max dsc bandwidth*/
|
||||
range->min_kbps = range->max_kbps;
|
||||
range->min_target_bpp_x16 = range->max_target_bpp_x16;
|
||||
}
|
||||
}
|
||||
|
||||
static bool decide_dsc_target_bpp_x16(
|
||||
const struct dc_dsc_policy *policy,
|
||||
const struct dsc_enc_caps *dsc_common_caps,
|
||||
const int target_bandwidth,
|
||||
const struct dc_crtc_timing *timing,
|
||||
int *target_bpp_x16)
|
||||
{
|
||||
bool should_use_dsc = false;
|
||||
struct dc_dsc_bw_range range;
|
||||
float target_bandwidth_kbps = target_bandwidth * 0.97f; // 3% overhead for FEC
|
||||
|
||||
memset(&range, 0, sizeof(range));
|
||||
|
||||
get_dsc_bandwidth_range(policy, dsc_common_caps, timing, &range);
|
||||
if (target_bandwidth_kbps >= range.stream_kbps) {
|
||||
/* enough bandwidth without dsc */
|
||||
*target_bpp_x16 = 0;
|
||||
should_use_dsc = false;
|
||||
} else if (target_bandwidth_kbps >= range.max_kbps) {
|
||||
/* use max target bpp allowed */
|
||||
*target_bpp_x16 = range.max_target_bpp_x16;
|
||||
should_use_dsc = true;
|
||||
} else if (target_bandwidth_kbps >= range.min_kbps) {
|
||||
/* use target bpp that can take entire target bandwidth */
|
||||
*target_bpp_x16 = calc_dsc_bpp_x16(target_bandwidth_kbps, timing->pix_clk_100hz, dsc_common_caps->bpp_increment_div);
|
||||
should_use_dsc = true;
|
||||
} else {
|
||||
/* not enough bandwidth to fulfill minimum requirement */
|
||||
*target_bpp_x16 = 0;
|
||||
should_use_dsc = false;
|
||||
}
|
||||
|
||||
return should_use_dsc;
|
||||
}
|
||||
|
||||
|
||||
#define MIN_AVAILABLE_SLICES_SIZE 4
|
||||
|
||||
static int get_available_dsc_slices(union dsc_enc_slice_caps slice_caps, int *available_slices)
|
||||
{
|
||||
int idx = 0;
|
||||
|
||||
memset(available_slices, -1, MIN_AVAILABLE_SLICES_SIZE);
|
||||
|
||||
if (slice_caps.bits.NUM_SLICES_1)
|
||||
available_slices[idx++] = 1;
|
||||
|
||||
if (slice_caps.bits.NUM_SLICES_2)
|
||||
available_slices[idx++] = 2;
|
||||
|
||||
if (slice_caps.bits.NUM_SLICES_4)
|
||||
available_slices[idx++] = 4;
|
||||
|
||||
if (slice_caps.bits.NUM_SLICES_8)
|
||||
available_slices[idx++] = 8;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
static int get_max_dsc_slices(union dsc_enc_slice_caps slice_caps)
|
||||
{
|
||||
int max_slices = 0;
|
||||
int available_slices[MIN_AVAILABLE_SLICES_SIZE];
|
||||
int end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]);
|
||||
|
||||
if (end_idx > 0)
|
||||
max_slices = available_slices[end_idx - 1];
|
||||
|
||||
return max_slices;
|
||||
}
|
||||
|
||||
|
||||
// Increment sice number in available sice numbers stops if possible, or just increment if not
|
||||
static int inc_num_slices(union dsc_enc_slice_caps slice_caps, int num_slices)
|
||||
{
|
||||
// Get next bigger num slices available in common caps
|
||||
int available_slices[MIN_AVAILABLE_SLICES_SIZE];
|
||||
int end_idx;
|
||||
int i;
|
||||
int new_num_slices = num_slices;
|
||||
|
||||
end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]);
|
||||
if (end_idx == 0) {
|
||||
// No available slices found
|
||||
new_num_slices++;
|
||||
return new_num_slices;
|
||||
}
|
||||
|
||||
// Numbers of slices found - get the next bigger number
|
||||
for (i = 0; i < end_idx; i++) {
|
||||
if (new_num_slices < available_slices[i]) {
|
||||
new_num_slices = available_slices[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_num_slices == num_slices) // No biger number of slices found
|
||||
new_num_slices++;
|
||||
|
||||
return new_num_slices;
|
||||
}
|
||||
|
||||
|
||||
// Decrement sice number in available sice numbers stops if possible, or just decrement if not. Stop at zero.
|
||||
static int dec_num_slices(union dsc_enc_slice_caps slice_caps, int num_slices)
|
||||
{
|
||||
// Get next bigger num slices available in common caps
|
||||
int available_slices[MIN_AVAILABLE_SLICES_SIZE];
|
||||
int end_idx;
|
||||
int i;
|
||||
int new_num_slices = num_slices;
|
||||
|
||||
end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]);
|
||||
if (end_idx == 0 && new_num_slices > 0) {
|
||||
// No numbers of slices found
|
||||
new_num_slices++;
|
||||
return new_num_slices;
|
||||
}
|
||||
|
||||
// Numbers of slices found - get the next smaller number
|
||||
for (i = end_idx - 1; i >= 0; i--) {
|
||||
if (new_num_slices > available_slices[i]) {
|
||||
new_num_slices = available_slices[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_num_slices == num_slices) {
|
||||
// No smaller number of slices found
|
||||
new_num_slices--;
|
||||
if (new_num_slices < 0)
|
||||
new_num_slices = 0;
|
||||
}
|
||||
|
||||
return new_num_slices;
|
||||
}
|
||||
|
||||
|
||||
// Choose next bigger number of slices if the requested number of slices is not available
|
||||
static int fit_num_slices_up(union dsc_enc_slice_caps slice_caps, int num_slices)
|
||||
{
|
||||
// Get next bigger num slices available in common caps
|
||||
int available_slices[MIN_AVAILABLE_SLICES_SIZE];
|
||||
int end_idx;
|
||||
int i;
|
||||
int new_num_slices = num_slices;
|
||||
|
||||
end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]);
|
||||
if (end_idx == 0) {
|
||||
// No available slices found
|
||||
new_num_slices++;
|
||||
return new_num_slices;
|
||||
}
|
||||
|
||||
// Numbers of slices found - get the equal or next bigger number
|
||||
for (i = 0; i < end_idx; i++) {
|
||||
if (new_num_slices <= available_slices[i]) {
|
||||
new_num_slices = available_slices[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new_num_slices;
|
||||
}
|
||||
|
||||
|
||||
/* Attempts to set DSC configuration for the stream, applying DSC policy.
|
||||
* Returns 'true' if successful or 'false' if not.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* dsc_sink_caps - DSC sink decoder capabilities (from DPCD)
|
||||
*
|
||||
* dsc_enc_caps - DSC encoder capabilities
|
||||
*
|
||||
* target_bandwidth - Target bandwidth to fit the stream into.
|
||||
* If 0, use maximum compression as per DSC policy.
|
||||
*
|
||||
* timing - The stream timing to fit into 'target_bandwidth' or apply
|
||||
* maximum compression to, if 'target_badwidth == 0'
|
||||
*
|
||||
* dsc_cfg - DSC configuration to use if it was possible to come up with
|
||||
* one for the given inputs.
|
||||
* The target bitrate after DSC can be calculated by multiplying
|
||||
* dsc_cfg.bits_per_pixel (in U6.4 format) by pixel rate, e.g.
|
||||
*
|
||||
* dsc_stream_bitrate_kbps = (int)ceil(timing->pix_clk_khz * dsc_cfg.bits_per_pixel / 16.0);
|
||||
*/
|
||||
static bool setup_dsc_config(
|
||||
const struct dsc_dec_dpcd_caps *dsc_sink_caps,
|
||||
const struct dsc_enc_caps *dsc_enc_caps,
|
||||
int target_bandwidth,
|
||||
const struct dc_crtc_timing *timing,
|
||||
struct dc_dsc_config *dsc_cfg)
|
||||
{
|
||||
struct dsc_enc_caps dsc_common_caps;
|
||||
int max_slices_h;
|
||||
int min_slices_h;
|
||||
int num_slices_h;
|
||||
int pic_width;
|
||||
int slice_width;
|
||||
int target_bpp;
|
||||
int sink_per_slice_throughput;
|
||||
// TODO DSC: See if it makes sense to use 2.4% for SST
|
||||
bool is_dsc_possible = false;
|
||||
int num_slices_v;
|
||||
int pic_height;
|
||||
|
||||
memset(dsc_cfg, 0, sizeof(struct dc_dsc_config));
|
||||
|
||||
if (!dsc_sink_caps->is_dsc_supported)
|
||||
goto done;
|
||||
|
||||
// Intersect decoder with encoder DSC caps and validate DSC settings
|
||||
is_dsc_possible = dc_intersect_dsc_caps(dsc_sink_caps, dsc_enc_caps, timing->pixel_encoding, &dsc_common_caps);
|
||||
if (!is_dsc_possible)
|
||||
goto done;
|
||||
|
||||
if (target_bandwidth > 0) {
|
||||
is_dsc_possible = decide_dsc_target_bpp_x16(&dsc_policy, &dsc_common_caps, target_bandwidth, timing, &target_bpp);
|
||||
} else if (timing->pix_clk_100hz * 12 <= calc_required_bandwidth_for_timing(timing) * 10) {
|
||||
/* use 12 target bpp for MST display
|
||||
* TODO: implement new MST DSC target bpp policy */
|
||||
target_bpp = 16*12;
|
||||
is_dsc_possible = true;
|
||||
} else {
|
||||
is_dsc_possible = false;
|
||||
}
|
||||
|
||||
if (!is_dsc_possible)
|
||||
goto done;
|
||||
|
||||
dsc_cfg->bits_per_pixel = target_bpp;
|
||||
|
||||
sink_per_slice_throughput = 0;
|
||||
|
||||
// Validate available DSC settings against the mode timing
|
||||
|
||||
// Color format
|
||||
dsc_cfg->ycbcr422_simple = false;
|
||||
switch (timing->pixel_encoding) {
|
||||
case PIXEL_ENCODING_RGB:
|
||||
is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.RGB;
|
||||
sink_per_slice_throughput = dsc_sink_caps->throughput_mode_0_mps;
|
||||
break;
|
||||
case PIXEL_ENCODING_YCBCR444:
|
||||
is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_444;
|
||||
sink_per_slice_throughput = dsc_sink_caps->throughput_mode_0_mps;
|
||||
break;
|
||||
case PIXEL_ENCODING_YCBCR422: {
|
||||
is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_422;
|
||||
sink_per_slice_throughput = dsc_sink_caps->throughput_mode_1_mps;
|
||||
if (!is_dsc_possible) {
|
||||
is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_SIMPLE_422;
|
||||
dsc_cfg->ycbcr422_simple = is_dsc_possible;
|
||||
sink_per_slice_throughput = dsc_sink_caps->throughput_mode_0_mps;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIXEL_ENCODING_YCBCR420:
|
||||
is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_420;
|
||||
sink_per_slice_throughput = dsc_sink_caps->throughput_mode_1_mps;
|
||||
break;
|
||||
default:
|
||||
is_dsc_possible = false;
|
||||
}
|
||||
|
||||
if (!is_dsc_possible)
|
||||
goto done;
|
||||
|
||||
// Color depth
|
||||
switch (timing->display_color_depth) {
|
||||
case COLOR_DEPTH_888:
|
||||
is_dsc_possible = (bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_8_BPC;
|
||||
break;
|
||||
case COLOR_DEPTH_101010:
|
||||
is_dsc_possible = (bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_10_BPC;
|
||||
break;
|
||||
case COLOR_DEPTH_121212:
|
||||
is_dsc_possible = (bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_12_BPC;
|
||||
break;
|
||||
default:
|
||||
is_dsc_possible = false;
|
||||
}
|
||||
|
||||
if (!is_dsc_possible)
|
||||
goto done;
|
||||
|
||||
// DSC slicing
|
||||
max_slices_h = get_max_dsc_slices(dsc_common_caps.slice_caps);
|
||||
|
||||
pic_width = timing->h_addressable + timing->h_border_left + timing->h_border_right;
|
||||
while (max_slices_h > 0) {
|
||||
if (pic_width % max_slices_h == 0)
|
||||
break;
|
||||
|
||||
max_slices_h = dec_num_slices(dsc_common_caps.slice_caps, max_slices_h);
|
||||
}
|
||||
|
||||
is_dsc_possible = (dsc_common_caps.max_slice_width > 0);
|
||||
if (!is_dsc_possible)
|
||||
goto done;
|
||||
|
||||
min_slices_h = pic_width / dsc_common_caps.max_slice_width;
|
||||
if (pic_width % dsc_common_caps.max_slice_width)
|
||||
min_slices_h++;
|
||||
|
||||
min_slices_h = fit_num_slices_up(dsc_common_caps.slice_caps, min_slices_h);
|
||||
|
||||
while (min_slices_h <= max_slices_h) {
|
||||
if (dsc_round_up(timing->pix_clk_100hz) / (min_slices_h) <= sink_per_slice_throughput * 1000)
|
||||
break;
|
||||
|
||||
min_slices_h = inc_num_slices(dsc_common_caps.slice_caps, min_slices_h);
|
||||
}
|
||||
|
||||
if (pic_width % min_slices_h != 0)
|
||||
min_slices_h = 0; // DSC TODO: Maybe try increasing the number of slices first?
|
||||
|
||||
is_dsc_possible = (min_slices_h <= max_slices_h);
|
||||
if (!is_dsc_possible)
|
||||
goto done;
|
||||
|
||||
if (dsc_policy.use_min_slices_h) {
|
||||
if (min_slices_h > 0)
|
||||
num_slices_h = min_slices_h;
|
||||
else if (max_slices_h > 0) { // Fall back to max slices if min slices is not working out
|
||||
if (dsc_policy.max_slices_h)
|
||||
num_slices_h = min(dsc_policy.max_slices_h, max_slices_h);
|
||||
else
|
||||
num_slices_h = max_slices_h;
|
||||
} else
|
||||
is_dsc_possible = false;
|
||||
} else {
|
||||
if (max_slices_h > 0) {
|
||||
if (dsc_policy.max_slices_h)
|
||||
num_slices_h = min(dsc_policy.max_slices_h, max_slices_h);
|
||||
else
|
||||
num_slices_h = max_slices_h;
|
||||
} else if (min_slices_h > 0) // Fall back to min slices if max slices is not possible
|
||||
num_slices_h = min_slices_h;
|
||||
else
|
||||
is_dsc_possible = false;
|
||||
}
|
||||
|
||||
if (!is_dsc_possible)
|
||||
goto done;
|
||||
|
||||
dsc_cfg->num_slices_h = num_slices_h;
|
||||
slice_width = pic_width / num_slices_h;
|
||||
|
||||
// Vertical number of slices: start from policy and pick the first one that height is divisible by
|
||||
pic_height = timing->v_addressable + timing->v_border_top + timing->v_border_bottom;
|
||||
num_slices_v = dsc_policy.num_slices_v;
|
||||
if (num_slices_v < 1)
|
||||
num_slices_v = 1;
|
||||
|
||||
while (num_slices_v >= 1 && (pic_height % num_slices_v != 0))
|
||||
num_slices_v--;
|
||||
|
||||
dsc_cfg->num_slices_v = num_slices_v;
|
||||
|
||||
is_dsc_possible = slice_width <= dsc_common_caps.max_slice_width;
|
||||
if (!is_dsc_possible)
|
||||
goto done;
|
||||
|
||||
// Final decission: can we do DSC or not?
|
||||
if (is_dsc_possible) {
|
||||
// Fill out the rest of DSC settings
|
||||
dsc_cfg->block_pred_enable = dsc_common_caps.is_block_pred_supported;
|
||||
dsc_cfg->linebuf_depth = dsc_common_caps.lb_bit_depth;
|
||||
dsc_cfg->version_minor = (dsc_common_caps.dsc_version & 0xf0) >> 4;
|
||||
}
|
||||
|
||||
done:
|
||||
if (!is_dsc_possible)
|
||||
memset(dsc_cfg, 0, sizeof(struct dc_dsc_config));
|
||||
|
||||
return is_dsc_possible;
|
||||
}
|
||||
|
||||
bool dc_dsc_parse_dsc_dpcd(const uint8_t *dpcd_dsc_data, struct dsc_dec_dpcd_caps *dsc_sink_caps)
|
||||
{
|
||||
dsc_sink_caps->is_dsc_supported = (dpcd_dsc_data[DP_DSC_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_DECOMPRESSION_IS_SUPPORTED) != 0;
|
||||
if (!dsc_sink_caps->is_dsc_supported)
|
||||
return true;
|
||||
|
||||
dsc_sink_caps->dsc_version = dpcd_dsc_data[DP_DSC_REV - DP_DSC_SUPPORT];
|
||||
|
||||
{
|
||||
int buff_block_size;
|
||||
int buff_size;
|
||||
|
||||
if (!dsc_buff_block_size_from_dpcd(dpcd_dsc_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT], &buff_block_size))
|
||||
return false;
|
||||
|
||||
buff_size = dpcd_dsc_data[DP_DSC_RC_BUF_SIZE - DP_DSC_SUPPORT] + 1;
|
||||
dsc_sink_caps->rc_buffer_size = buff_size * buff_block_size;
|
||||
}
|
||||
|
||||
dsc_sink_caps->slice_caps1.raw = dpcd_dsc_data[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT];
|
||||
if (!dsc_line_buff_depth_from_dpcd(dpcd_dsc_data[DP_DSC_LINE_BUF_BIT_DEPTH - DP_DSC_SUPPORT], &dsc_sink_caps->lb_bit_depth))
|
||||
return false;
|
||||
|
||||
dsc_sink_caps->is_block_pred_supported =
|
||||
(dpcd_dsc_data[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_BLK_PREDICTION_IS_SUPPORTED) != 0;
|
||||
|
||||
dsc_sink_caps->edp_max_bits_per_pixel =
|
||||
dpcd_dsc_data[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] |
|
||||
dpcd_dsc_data[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] << 8;
|
||||
|
||||
dsc_sink_caps->color_formats.raw = dpcd_dsc_data[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT];
|
||||
dsc_sink_caps->color_depth.raw = dpcd_dsc_data[DP_DSC_DEC_COLOR_DEPTH_CAP - DP_DSC_SUPPORT];
|
||||
|
||||
{
|
||||
int dpcd_throughput = dpcd_dsc_data[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT];
|
||||
|
||||
if (!dsc_throughput_from_dpcd(dpcd_throughput & DP_DSC_THROUGHPUT_MODE_0_MASK, &dsc_sink_caps->throughput_mode_0_mps))
|
||||
return false;
|
||||
|
||||
dpcd_throughput = (dpcd_throughput & DP_DSC_THROUGHPUT_MODE_1_MASK) >> DP_DSC_THROUGHPUT_MODE_1_SHIFT;
|
||||
if (!dsc_throughput_from_dpcd(dpcd_throughput, &dsc_sink_caps->throughput_mode_1_mps))
|
||||
return false;
|
||||
}
|
||||
|
||||
dsc_sink_caps->max_slice_width = dpcd_dsc_data[DP_DSC_MAX_SLICE_WIDTH - DP_DSC_SUPPORT] * 320;
|
||||
dsc_sink_caps->slice_caps2.raw = dpcd_dsc_data[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT];
|
||||
|
||||
if (!dsc_bpp_increment_div_from_dpcd(dpcd_dsc_data[DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT], &dsc_sink_caps->bpp_increment_div))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool dc_dsc_compute_bandwidth_range(
|
||||
const struct dc *dc,
|
||||
const struct dsc_dec_dpcd_caps *dsc_sink_caps,
|
||||
const struct dc_crtc_timing *timing,
|
||||
struct dc_dsc_bw_range *range)
|
||||
{
|
||||
bool is_dsc_possible = false;
|
||||
struct dsc_enc_caps dsc_enc_caps;
|
||||
struct dsc_enc_caps dsc_common_caps;
|
||||
get_dsc_enc_caps(dc, &dsc_enc_caps, timing->pix_clk_100hz);
|
||||
is_dsc_possible = dc_intersect_dsc_caps(dsc_sink_caps, &dsc_enc_caps, timing->pixel_encoding, &dsc_common_caps);
|
||||
if (is_dsc_possible)
|
||||
get_dsc_bandwidth_range(&dsc_policy, &dsc_common_caps, timing, range);
|
||||
return is_dsc_possible;
|
||||
}
|
||||
|
||||
bool dc_dsc_compute_config(
|
||||
const struct dc *dc,
|
||||
const struct dsc_dec_dpcd_caps *dsc_sink_caps,
|
||||
int target_bandwidth,
|
||||
const struct dc_crtc_timing *timing,
|
||||
struct dc_dsc_config *dsc_cfg)
|
||||
{
|
||||
bool is_dsc_possible = false;
|
||||
|
||||
struct dsc_enc_caps dsc_enc_caps;
|
||||
struct dsc_enc_caps dsc_common_caps;
|
||||
|
||||
get_dsc_enc_caps(dc, &dsc_enc_caps, timing->pix_clk_100hz);
|
||||
is_dsc_possible = dc_intersect_dsc_caps(dsc_sink_caps, &dsc_enc_caps,
|
||||
timing->pixel_encoding, &dsc_common_caps);
|
||||
if (is_dsc_possible)
|
||||
is_dsc_possible = setup_dsc_config(dsc_sink_caps,
|
||||
&dsc_enc_caps,
|
||||
target_bandwidth,
|
||||
timing, dsc_cfg);
|
||||
return is_dsc_possible;
|
||||
}
|
||||
|
||||
bool dc_check_and_fit_timing_into_bandwidth_with_dsc_legacy(
|
||||
const struct dc *pDC,
|
||||
const struct dc_link *link,
|
||||
struct dc_crtc_timing *timing)
|
||||
{
|
||||
int requiredBandwidth_Kbps;
|
||||
bool stream_fits_into_bandwidth = false;
|
||||
int link_rate_kbytes_per_sec = link->verified_link_cap.link_rate * LINK_RATE_REF_FREQ_IN_KHZ;
|
||||
int total_link_bandwdith_kbps = link->verified_link_cap.lane_count * link_rate_kbytes_per_sec * 8;
|
||||
|
||||
if (link->preferred_link_setting.lane_count !=
|
||||
LANE_COUNT_UNKNOWN &&
|
||||
link->preferred_link_setting.link_rate !=
|
||||
LINK_RATE_UNKNOWN) {
|
||||
link_rate_kbytes_per_sec = link->preferred_link_setting.link_rate * LINK_RATE_REF_FREQ_IN_KHZ;
|
||||
total_link_bandwdith_kbps = link->preferred_link_setting.lane_count * link_rate_kbytes_per_sec * 8;
|
||||
}
|
||||
|
||||
timing->flags.DSC = 0;
|
||||
requiredBandwidth_Kbps = calc_required_bandwidth_for_timing(timing);
|
||||
|
||||
if (total_link_bandwdith_kbps >= requiredBandwidth_Kbps)
|
||||
stream_fits_into_bandwidth = true;
|
||||
else {
|
||||
// There's not enough bandwidth in the link. See if DSC can be used to resolve this.
|
||||
int link_bandwidth_kbps = link->type == dc_connection_mst_branch ? 0 : total_link_bandwdith_kbps;
|
||||
|
||||
stream_fits_into_bandwidth = dc_setup_dsc_in_timing_legacy(pDC, &link->dpcd_caps.dsc_sink_caps, link_bandwidth_kbps, timing);
|
||||
}
|
||||
|
||||
return stream_fits_into_bandwidth;
|
||||
}
|
||||
|
||||
bool dc_setup_dsc_in_timing_legacy(const struct dc *pDC,
|
||||
const struct dsc_dec_dpcd_caps *dsc_sink_caps,
|
||||
int available_bandwidth_kbps,
|
||||
struct dc_crtc_timing *timing)
|
||||
{
|
||||
bool isDscOK = false;
|
||||
struct dsc_enc_caps dsc_enc_caps;
|
||||
|
||||
timing->flags.DSC = 0;
|
||||
get_dsc_enc_caps(pDC, &dsc_enc_caps, timing->pix_clk_100hz);
|
||||
if (dsc_enc_caps.dsc_version) {
|
||||
struct dc_dsc_config dscCfg = {0};
|
||||
|
||||
isDscOK = setup_dsc_config(dsc_sink_caps, &dsc_enc_caps, available_bandwidth_kbps, timing, &dscCfg);
|
||||
|
||||
memcpy(&timing->dsc_cfg, &dscCfg, sizeof(dscCfg));
|
||||
timing->flags.DSC = isDscOK ? 1 : 0;
|
||||
}
|
||||
|
||||
return isDscOK;
|
||||
}
|
||||
#endif /* CONFIG_DRM_AMD_DC_DSC_SUPPORT */
|
382
drivers/gpu/drm/amd/display/dc/dsc/drm_dsc_dc.c
Normal file
382
drivers/gpu/drm/amd/display/dc/dsc/drm_dsc_dc.c
Normal file
@ -0,0 +1,382 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2018 Intel Corp
|
||||
*
|
||||
* Author:
|
||||
* Manasi Navare <manasi.d.navare@intel.com>
|
||||
*/
|
||||
|
||||
/* DC versions of linux includes */
|
||||
#include <include/drm_dsc_dc.h>
|
||||
|
||||
#define EXPORT_SYMBOL(symbol) /* nothing */
|
||||
#define BUILD_BUG_ON(cond) /* nothing */
|
||||
#define DIV_ROUND_UP(a, b) (((b) + (a) - 1) / (b))
|
||||
#define ERANGE -1
|
||||
#define DRM_DEBUG_KMS(msg) /* nothing */
|
||||
#define cpu_to_be16(__x) little_to_big(__x)
|
||||
|
||||
static unsigned short little_to_big(int data)
|
||||
{
|
||||
/* Swap lower and upper byte. DMCU uses big endian format. */
|
||||
return (0xff & (data >> 8)) + ((data & 0xff) << 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Everything below this comment was copied directly from drm_dsc.c.
|
||||
* Only the functions needed in DC are included.
|
||||
* Please keep this file synced with upstream.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: dsc helpers
|
||||
*
|
||||
* These functions contain some common logic and helpers to deal with VESA
|
||||
* Display Stream Compression standard required for DSC on Display Port/eDP or
|
||||
* MIPI display interfaces.
|
||||
*/
|
||||
|
||||
/**
|
||||
* drm_dsc_pps_payload_pack() - Populates the DSC PPS
|
||||
*
|
||||
* @pps_payload:
|
||||
* Bitwise struct for DSC Picture Parameter Set. This is defined
|
||||
* by &struct drm_dsc_picture_parameter_set
|
||||
* @dsc_cfg:
|
||||
* DSC Configuration data filled by driver as defined by
|
||||
* &struct drm_dsc_config
|
||||
*
|
||||
* DSC source device sends a picture parameter set (PPS) containing the
|
||||
* information required by the sink to decode the compressed frame. Driver
|
||||
* populates the DSC PPS struct using the DSC configuration parameters in
|
||||
* the order expected by the DSC Display Sink device. For the DSC, the sink
|
||||
* device expects the PPS payload in big endian format for fields
|
||||
* that span more than 1 byte.
|
||||
*/
|
||||
void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set *pps_payload,
|
||||
const struct drm_dsc_config *dsc_cfg)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Protect against someone accidently changing struct size */
|
||||
BUILD_BUG_ON(sizeof(*pps_payload) !=
|
||||
DP_SDP_PPS_HEADER_PAYLOAD_BYTES_MINUS_1 + 1);
|
||||
|
||||
memset(pps_payload, 0, sizeof(*pps_payload));
|
||||
|
||||
/* PPS 0 */
|
||||
pps_payload->dsc_version =
|
||||
dsc_cfg->dsc_version_minor |
|
||||
dsc_cfg->dsc_version_major << DSC_PPS_VERSION_MAJOR_SHIFT;
|
||||
|
||||
/* PPS 1, 2 is 0 */
|
||||
|
||||
/* PPS 3 */
|
||||
pps_payload->pps_3 =
|
||||
dsc_cfg->line_buf_depth |
|
||||
dsc_cfg->bits_per_component << DSC_PPS_BPC_SHIFT;
|
||||
|
||||
/* PPS 4 */
|
||||
pps_payload->pps_4 =
|
||||
((dsc_cfg->bits_per_pixel & DSC_PPS_BPP_HIGH_MASK) >>
|
||||
DSC_PPS_MSB_SHIFT) |
|
||||
dsc_cfg->vbr_enable << DSC_PPS_VBR_EN_SHIFT |
|
||||
dsc_cfg->simple_422 << DSC_PPS_SIMPLE422_SHIFT |
|
||||
dsc_cfg->convert_rgb << DSC_PPS_CONVERT_RGB_SHIFT |
|
||||
dsc_cfg->block_pred_enable << DSC_PPS_BLOCK_PRED_EN_SHIFT;
|
||||
|
||||
/* PPS 5 */
|
||||
pps_payload->bits_per_pixel_low =
|
||||
(dsc_cfg->bits_per_pixel & DSC_PPS_LSB_MASK);
|
||||
|
||||
/*
|
||||
* The DSC panel expects the PPS packet to have big endian format
|
||||
* for data spanning 2 bytes. Use a macro cpu_to_be16() to convert
|
||||
* to big endian format. If format is little endian, it will swap
|
||||
* bytes to convert to Big endian else keep it unchanged.
|
||||
*/
|
||||
|
||||
/* PPS 6, 7 */
|
||||
pps_payload->pic_height = cpu_to_be16(dsc_cfg->pic_height);
|
||||
|
||||
/* PPS 8, 9 */
|
||||
pps_payload->pic_width = cpu_to_be16(dsc_cfg->pic_width);
|
||||
|
||||
/* PPS 10, 11 */
|
||||
pps_payload->slice_height = cpu_to_be16(dsc_cfg->slice_height);
|
||||
|
||||
/* PPS 12, 13 */
|
||||
pps_payload->slice_width = cpu_to_be16(dsc_cfg->slice_width);
|
||||
|
||||
/* PPS 14, 15 */
|
||||
pps_payload->chunk_size = cpu_to_be16(dsc_cfg->slice_chunk_size);
|
||||
|
||||
/* PPS 16 */
|
||||
pps_payload->initial_xmit_delay_high =
|
||||
((dsc_cfg->initial_xmit_delay &
|
||||
DSC_PPS_INIT_XMIT_DELAY_HIGH_MASK) >>
|
||||
DSC_PPS_MSB_SHIFT);
|
||||
|
||||
/* PPS 17 */
|
||||
pps_payload->initial_xmit_delay_low =
|
||||
(dsc_cfg->initial_xmit_delay & DSC_PPS_LSB_MASK);
|
||||
|
||||
/* PPS 18, 19 */
|
||||
pps_payload->initial_dec_delay =
|
||||
cpu_to_be16(dsc_cfg->initial_dec_delay);
|
||||
|
||||
/* PPS 20 is 0 */
|
||||
|
||||
/* PPS 21 */
|
||||
pps_payload->initial_scale_value =
|
||||
dsc_cfg->initial_scale_value;
|
||||
|
||||
/* PPS 22, 23 */
|
||||
pps_payload->scale_increment_interval =
|
||||
cpu_to_be16(dsc_cfg->scale_increment_interval);
|
||||
|
||||
/* PPS 24 */
|
||||
pps_payload->scale_decrement_interval_high =
|
||||
((dsc_cfg->scale_decrement_interval &
|
||||
DSC_PPS_SCALE_DEC_INT_HIGH_MASK) >>
|
||||
DSC_PPS_MSB_SHIFT);
|
||||
|
||||
/* PPS 25 */
|
||||
pps_payload->scale_decrement_interval_low =
|
||||
(dsc_cfg->scale_decrement_interval & DSC_PPS_LSB_MASK);
|
||||
|
||||
/* PPS 26[7:0], PPS 27[7:5] RESERVED */
|
||||
|
||||
/* PPS 27 */
|
||||
pps_payload->first_line_bpg_offset =
|
||||
dsc_cfg->first_line_bpg_offset;
|
||||
|
||||
/* PPS 28, 29 */
|
||||
pps_payload->nfl_bpg_offset =
|
||||
cpu_to_be16(dsc_cfg->nfl_bpg_offset);
|
||||
|
||||
/* PPS 30, 31 */
|
||||
pps_payload->slice_bpg_offset =
|
||||
cpu_to_be16(dsc_cfg->slice_bpg_offset);
|
||||
|
||||
/* PPS 32, 33 */
|
||||
pps_payload->initial_offset =
|
||||
cpu_to_be16(dsc_cfg->initial_offset);
|
||||
|
||||
/* PPS 34, 35 */
|
||||
pps_payload->final_offset = cpu_to_be16(dsc_cfg->final_offset);
|
||||
|
||||
/* PPS 36 */
|
||||
pps_payload->flatness_min_qp = dsc_cfg->flatness_min_qp;
|
||||
|
||||
/* PPS 37 */
|
||||
pps_payload->flatness_max_qp = dsc_cfg->flatness_max_qp;
|
||||
|
||||
/* PPS 38, 39 */
|
||||
pps_payload->rc_model_size =
|
||||
cpu_to_be16(DSC_RC_MODEL_SIZE_CONST);
|
||||
|
||||
/* PPS 40 */
|
||||
pps_payload->rc_edge_factor = DSC_RC_EDGE_FACTOR_CONST;
|
||||
|
||||
/* PPS 41 */
|
||||
pps_payload->rc_quant_incr_limit0 =
|
||||
dsc_cfg->rc_quant_incr_limit0;
|
||||
|
||||
/* PPS 42 */
|
||||
pps_payload->rc_quant_incr_limit1 =
|
||||
dsc_cfg->rc_quant_incr_limit1;
|
||||
|
||||
/* PPS 43 */
|
||||
pps_payload->rc_tgt_offset = DSC_RC_TGT_OFFSET_LO_CONST |
|
||||
DSC_RC_TGT_OFFSET_HI_CONST << DSC_PPS_RC_TGT_OFFSET_HI_SHIFT;
|
||||
|
||||
/* PPS 44 - 57 */
|
||||
for (i = 0; i < DSC_NUM_BUF_RANGES - 1; i++)
|
||||
pps_payload->rc_buf_thresh[i] =
|
||||
dsc_cfg->rc_buf_thresh[i];
|
||||
|
||||
/* PPS 58 - 87 */
|
||||
/*
|
||||
* For DSC sink programming the RC Range parameter fields
|
||||
* are as follows: Min_qp[15:11], max_qp[10:6], offset[5:0]
|
||||
*/
|
||||
for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
|
||||
pps_payload->rc_range_parameters[i] =
|
||||
((dsc_cfg->rc_range_params[i].range_min_qp <<
|
||||
DSC_PPS_RC_RANGE_MINQP_SHIFT) |
|
||||
(dsc_cfg->rc_range_params[i].range_max_qp <<
|
||||
DSC_PPS_RC_RANGE_MAXQP_SHIFT) |
|
||||
(dsc_cfg->rc_range_params[i].range_bpg_offset));
|
||||
pps_payload->rc_range_parameters[i] =
|
||||
cpu_to_be16(pps_payload->rc_range_parameters[i]);
|
||||
}
|
||||
|
||||
/* PPS 88 */
|
||||
pps_payload->native_422_420 = dsc_cfg->native_422 |
|
||||
dsc_cfg->native_420 << DSC_PPS_NATIVE_420_SHIFT;
|
||||
|
||||
/* PPS 89 */
|
||||
pps_payload->second_line_bpg_offset =
|
||||
dsc_cfg->second_line_bpg_offset;
|
||||
|
||||
/* PPS 90, 91 */
|
||||
pps_payload->nsl_bpg_offset =
|
||||
cpu_to_be16(dsc_cfg->nsl_bpg_offset);
|
||||
|
||||
/* PPS 92, 93 */
|
||||
pps_payload->second_line_offset_adj =
|
||||
cpu_to_be16(dsc_cfg->second_line_offset_adj);
|
||||
|
||||
/* PPS 94 - 127 are O */
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dsc_pps_payload_pack);
|
||||
|
||||
/**
|
||||
* drm_dsc_compute_rc_parameters() - Write rate control
|
||||
* parameters to the dsc configuration defined in
|
||||
* &struct drm_dsc_config in accordance with the DSC 1.2
|
||||
* specification. Some configuration fields must be present
|
||||
* beforehand.
|
||||
*
|
||||
* @vdsc_cfg:
|
||||
* DSC Configuration data partially filled by driver
|
||||
*/
|
||||
int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg)
|
||||
{
|
||||
unsigned long groups_per_line = 0;
|
||||
unsigned long groups_total = 0;
|
||||
unsigned long num_extra_mux_bits = 0;
|
||||
unsigned long slice_bits = 0;
|
||||
unsigned long hrd_delay = 0;
|
||||
unsigned long final_scale = 0;
|
||||
unsigned long rbs_min = 0;
|
||||
|
||||
if (vdsc_cfg->native_420 || vdsc_cfg->native_422) {
|
||||
/* Number of groups used to code each line of a slice */
|
||||
groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width / 2,
|
||||
DSC_RC_PIXELS_PER_GROUP);
|
||||
|
||||
/* chunksize in Bytes */
|
||||
vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width / 2 *
|
||||
vdsc_cfg->bits_per_pixel,
|
||||
(8 * 16));
|
||||
} else {
|
||||
/* Number of groups used to code each line of a slice */
|
||||
groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width,
|
||||
DSC_RC_PIXELS_PER_GROUP);
|
||||
|
||||
/* chunksize in Bytes */
|
||||
vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width *
|
||||
vdsc_cfg->bits_per_pixel,
|
||||
(8 * 16));
|
||||
}
|
||||
|
||||
if (vdsc_cfg->convert_rgb)
|
||||
num_extra_mux_bits = 3 * (vdsc_cfg->mux_word_size +
|
||||
(4 * vdsc_cfg->bits_per_component + 4)
|
||||
- 2);
|
||||
else if (vdsc_cfg->native_422)
|
||||
num_extra_mux_bits = 4 * vdsc_cfg->mux_word_size +
|
||||
(4 * vdsc_cfg->bits_per_component + 4) +
|
||||
3 * (4 * vdsc_cfg->bits_per_component) - 2;
|
||||
else
|
||||
num_extra_mux_bits = 3 * vdsc_cfg->mux_word_size +
|
||||
(4 * vdsc_cfg->bits_per_component + 4) +
|
||||
2 * (4 * vdsc_cfg->bits_per_component) - 2;
|
||||
/* Number of bits in one Slice */
|
||||
slice_bits = 8 * vdsc_cfg->slice_chunk_size * vdsc_cfg->slice_height;
|
||||
|
||||
while ((num_extra_mux_bits > 0) &&
|
||||
((slice_bits - num_extra_mux_bits) % vdsc_cfg->mux_word_size))
|
||||
num_extra_mux_bits--;
|
||||
|
||||
if (groups_per_line < vdsc_cfg->initial_scale_value - 8)
|
||||
vdsc_cfg->initial_scale_value = groups_per_line + 8;
|
||||
|
||||
/* scale_decrement_interval calculation according to DSC spec 1.11 */
|
||||
if (vdsc_cfg->initial_scale_value > 8)
|
||||
vdsc_cfg->scale_decrement_interval = groups_per_line /
|
||||
(vdsc_cfg->initial_scale_value - 8);
|
||||
else
|
||||
vdsc_cfg->scale_decrement_interval = DSC_SCALE_DECREMENT_INTERVAL_MAX;
|
||||
|
||||
vdsc_cfg->final_offset = vdsc_cfg->rc_model_size -
|
||||
(vdsc_cfg->initial_xmit_delay *
|
||||
vdsc_cfg->bits_per_pixel + 8) / 16 + num_extra_mux_bits;
|
||||
|
||||
if (vdsc_cfg->final_offset >= vdsc_cfg->rc_model_size) {
|
||||
DRM_DEBUG_KMS("FinalOfs < RcModelSze for this InitialXmitDelay\n");
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
final_scale = (vdsc_cfg->rc_model_size * 8) /
|
||||
(vdsc_cfg->rc_model_size - vdsc_cfg->final_offset);
|
||||
if (vdsc_cfg->slice_height > 1)
|
||||
/*
|
||||
* NflBpgOffset is 16 bit value with 11 fractional bits
|
||||
* hence we multiply by 2^11 for preserving the
|
||||
* fractional part
|
||||
*/
|
||||
vdsc_cfg->nfl_bpg_offset = DIV_ROUND_UP((vdsc_cfg->first_line_bpg_offset << 11),
|
||||
(vdsc_cfg->slice_height - 1));
|
||||
else
|
||||
vdsc_cfg->nfl_bpg_offset = 0;
|
||||
|
||||
/* 2^16 - 1 */
|
||||
if (vdsc_cfg->nfl_bpg_offset > 65535) {
|
||||
DRM_DEBUG_KMS("NflBpgOffset is too large for this slice height\n");
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
/* Number of groups used to code the entire slice */
|
||||
groups_total = groups_per_line * vdsc_cfg->slice_height;
|
||||
|
||||
/* slice_bpg_offset is 16 bit value with 11 fractional bits */
|
||||
vdsc_cfg->slice_bpg_offset = DIV_ROUND_UP(((vdsc_cfg->rc_model_size -
|
||||
vdsc_cfg->initial_offset +
|
||||
num_extra_mux_bits) << 11),
|
||||
groups_total);
|
||||
|
||||
if (final_scale > 9) {
|
||||
/*
|
||||
* ScaleIncrementInterval =
|
||||
* finaloffset/((NflBpgOffset + SliceBpgOffset)*8(finalscale - 1.125))
|
||||
* as (NflBpgOffset + SliceBpgOffset) has 11 bit fractional value,
|
||||
* we need divide by 2^11 from pstDscCfg values
|
||||
*/
|
||||
vdsc_cfg->scale_increment_interval =
|
||||
(vdsc_cfg->final_offset * (1 << 11)) /
|
||||
((vdsc_cfg->nfl_bpg_offset +
|
||||
vdsc_cfg->slice_bpg_offset) *
|
||||
(final_scale - 9));
|
||||
} else {
|
||||
/*
|
||||
* If finalScaleValue is less than or equal to 9, a value of 0 should
|
||||
* be used to disable the scale increment at the end of the slice
|
||||
*/
|
||||
vdsc_cfg->scale_increment_interval = 0;
|
||||
}
|
||||
|
||||
if (vdsc_cfg->scale_increment_interval > 65535) {
|
||||
DRM_DEBUG_KMS("ScaleIncrementInterval is large for slice height\n");
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
/*
|
||||
* DSC spec mentions that bits_per_pixel specifies the target
|
||||
* bits/pixel (bpp) rate that is used by the encoder,
|
||||
* in steps of 1/16 of a bit per pixel
|
||||
*/
|
||||
rbs_min = vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset +
|
||||
DIV_ROUND_UP(vdsc_cfg->initial_xmit_delay *
|
||||
vdsc_cfg->bits_per_pixel, 16) +
|
||||
groups_per_line * vdsc_cfg->first_line_bpg_offset;
|
||||
|
||||
hrd_delay = DIV_ROUND_UP((rbs_min * 16), vdsc_cfg->bits_per_pixel);
|
||||
vdsc_cfg->rc_bits = (hrd_delay * vdsc_cfg->bits_per_pixel) / 16;
|
||||
vdsc_cfg->initial_dec_delay = hrd_delay - vdsc_cfg->initial_xmit_delay;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dsc_compute_rc_parameters);
|
243
drivers/gpu/drm/amd/display/dc/dsc/dsc_helpers.c
Normal file
243
drivers/gpu/drm/amd/display/dc/dsc/dsc_helpers.c
Normal file
@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright 2018 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
|
||||
#include "dc.h"
|
||||
#include "dsc.h"
|
||||
#include "dc_hw_types.h"
|
||||
#include <drm/drm_dp_helper.h>
|
||||
|
||||
#define DC_LOGGER \
|
||||
dsc->ctx->logger
|
||||
|
||||
static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size);
|
||||
static bool dsc_line_buff_depth_from_dpcd(int dpcd_line_buff_bit_depth, int *line_buff_bit_depth);
|
||||
static bool dsc_throughput_from_dpcd(int dpcd_throughput, int *throughput);
|
||||
static bool dsc_bpp_increment_div_from_dpcd(int bpp_increment_dpcd, uint32_t *bpp_increment_div);
|
||||
|
||||
void dsc_optc_config_log(struct display_stream_compressor *dsc,
|
||||
struct dsc_optc_config *config)
|
||||
{
|
||||
DC_LOG_DSC("Setting optc DSC config at DSC inst %d", dsc->inst);
|
||||
DC_LOG_DSC("\n\tbytes_per_pixel %d\n\tis_pixel_format_444 %d\n\tslice_width %d",
|
||||
config->bytes_per_pixel,
|
||||
config->is_pixel_format_444, config->slice_width);
|
||||
}
|
||||
|
||||
void dsc_config_log(struct display_stream_compressor *dsc,
|
||||
const struct dsc_config *config)
|
||||
{
|
||||
DC_LOG_DSC("Setting DSC Config at DSC inst %d", dsc->inst);
|
||||
DC_LOG_DSC("\n\tnum_slices_h %d\n\tnum_slices_v %d\n\tbits_per_pixel %d\n\tcolor_depth %d",
|
||||
config->dc_dsc_cfg.num_slices_h,
|
||||
config->dc_dsc_cfg.num_slices_v,
|
||||
config->dc_dsc_cfg.bits_per_pixel,
|
||||
config->color_depth);
|
||||
}
|
||||
|
||||
|
||||
bool dsc_parse_dsc_dpcd(const uint8_t *dpcd_dsc_data, struct dsc_dec_dpcd_caps *dsc_sink_caps)
|
||||
{
|
||||
dsc_sink_caps->is_dsc_supported = (dpcd_dsc_data[DP_DSC_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_DECOMPRESSION_IS_SUPPORTED) != 0;
|
||||
if (!dsc_sink_caps->is_dsc_supported)
|
||||
return true;
|
||||
|
||||
dsc_sink_caps->dsc_version = dpcd_dsc_data[DP_DSC_REV - DP_DSC_SUPPORT];
|
||||
|
||||
{
|
||||
int buff_block_size;
|
||||
int buff_size;
|
||||
|
||||
if (!dsc_buff_block_size_from_dpcd(dpcd_dsc_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT], &buff_block_size))
|
||||
return false;
|
||||
|
||||
buff_size = dpcd_dsc_data[DP_DSC_RC_BUF_SIZE - DP_DSC_SUPPORT] + 1;
|
||||
dsc_sink_caps->rc_buffer_size = buff_size * buff_block_size;
|
||||
}
|
||||
|
||||
dsc_sink_caps->slice_caps1.raw = dpcd_dsc_data[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT];
|
||||
if (!dsc_line_buff_depth_from_dpcd(dpcd_dsc_data[DP_DSC_LINE_BUF_BIT_DEPTH - DP_DSC_SUPPORT], &dsc_sink_caps->lb_bit_depth))
|
||||
return false;
|
||||
|
||||
dsc_sink_caps->is_block_pred_supported =
|
||||
(dpcd_dsc_data[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_BLK_PREDICTION_IS_SUPPORTED) != 0;
|
||||
|
||||
dsc_sink_caps->edp_max_bits_per_pixel =
|
||||
dpcd_dsc_data[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] |
|
||||
dpcd_dsc_data[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] << 8;
|
||||
|
||||
dsc_sink_caps->color_formats.raw = dpcd_dsc_data[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT];
|
||||
dsc_sink_caps->color_depth.raw = dpcd_dsc_data[DP_DSC_DEC_COLOR_DEPTH_CAP - DP_DSC_SUPPORT];
|
||||
|
||||
{
|
||||
int dpcd_throughput = dpcd_dsc_data[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT];
|
||||
|
||||
if (!dsc_throughput_from_dpcd(dpcd_throughput & DP_DSC_THROUGHPUT_MODE_0_MASK, &dsc_sink_caps->throughput_mode_0_mps))
|
||||
return false;
|
||||
|
||||
dpcd_throughput = (dpcd_throughput & DP_DSC_THROUGHPUT_MODE_1_MASK) >> DP_DSC_THROUGHPUT_MODE_1_SHIFT;
|
||||
if (!dsc_throughput_from_dpcd(dpcd_throughput, &dsc_sink_caps->throughput_mode_1_mps))
|
||||
return false;
|
||||
}
|
||||
|
||||
dsc_sink_caps->max_slice_width = dpcd_dsc_data[DP_DSC_MAX_SLICE_WIDTH - DP_DSC_SUPPORT] * 320;
|
||||
dsc_sink_caps->slice_caps2.raw = dpcd_dsc_data[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT];
|
||||
|
||||
if (!dsc_bpp_increment_div_from_dpcd(dpcd_dsc_data[DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT], &dsc_sink_caps->bpp_increment_div))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* This module's internal functions */
|
||||
|
||||
static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size)
|
||||
{
|
||||
|
||||
switch (dpcd_buff_block_size) {
|
||||
case DP_DSC_RC_BUF_BLK_SIZE_1:
|
||||
*buff_block_size = 1024;
|
||||
break;
|
||||
case DP_DSC_RC_BUF_BLK_SIZE_4:
|
||||
*buff_block_size = 4 * 1024;
|
||||
break;
|
||||
case DP_DSC_RC_BUF_BLK_SIZE_16:
|
||||
*buff_block_size = 16 * 1024;
|
||||
break;
|
||||
case DP_DSC_RC_BUF_BLK_SIZE_64:
|
||||
*buff_block_size = 64 * 1024;
|
||||
break;
|
||||
default: {
|
||||
dm_error("%s: DPCD DSC buffer size not recoginzed.\n", __func__);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool dsc_line_buff_depth_from_dpcd(int dpcd_line_buff_bit_depth, int *line_buff_bit_depth)
|
||||
{
|
||||
if (0 <= dpcd_line_buff_bit_depth && dpcd_line_buff_bit_depth <= 7)
|
||||
*line_buff_bit_depth = dpcd_line_buff_bit_depth + 9;
|
||||
else if (dpcd_line_buff_bit_depth == 8)
|
||||
*line_buff_bit_depth = 8;
|
||||
else {
|
||||
dm_error("%s: DPCD DSC buffer depth not recoginzed.\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool dsc_throughput_from_dpcd(int dpcd_throughput, int *throughput)
|
||||
{
|
||||
switch (dpcd_throughput) {
|
||||
case DP_DSC_THROUGHPUT_MODE_0_340:
|
||||
*throughput = 340;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_400:
|
||||
*throughput = 400;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_450:
|
||||
*throughput = 450;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_500:
|
||||
*throughput = 500;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_550:
|
||||
*throughput = 550;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_600:
|
||||
*throughput = 600;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_650:
|
||||
*throughput = 650;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_700:
|
||||
*throughput = 700;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_750:
|
||||
*throughput = 750;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_800:
|
||||
*throughput = 800;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_850:
|
||||
*throughput = 850;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_900:
|
||||
*throughput = 900;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_950:
|
||||
*throughput = 950;
|
||||
break;
|
||||
case DP_DSC_THROUGHPUT_MODE_0_1000:
|
||||
*throughput = 1000;
|
||||
break;
|
||||
default: {
|
||||
dm_error("%s: DPCD DSC througput mode not recoginzed.\n", __func__);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool dsc_bpp_increment_div_from_dpcd(int bpp_increment_dpcd, uint32_t *bpp_increment_div)
|
||||
{
|
||||
|
||||
switch (bpp_increment_dpcd) {
|
||||
case 0:
|
||||
*bpp_increment_div = 16;
|
||||
break;
|
||||
case 1:
|
||||
*bpp_increment_div = 8;
|
||||
break;
|
||||
case 2:
|
||||
*bpp_increment_div = 4;
|
||||
break;
|
||||
case 3:
|
||||
*bpp_increment_div = 2;
|
||||
break;
|
||||
case 4:
|
||||
*bpp_increment_div = 1;
|
||||
break;
|
||||
default: {
|
||||
dm_error("%s: DPCD DSC bits-per-pixel increment not recoginzed.\n", __func__);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif // CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
54
drivers/gpu/drm/amd/display/dc/dsc/dscc_types.h
Normal file
54
drivers/gpu/drm/amd/display/dc/dsc/dscc_types.h
Normal file
@ -0,0 +1,54 @@
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
|
||||
|
||||
/*
|
||||
* Copyright 2017 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 __DSCC_TYPES_H__
|
||||
#define __DSCC_TYPES_H__
|
||||
|
||||
#include <drm/drm_dsc.h>
|
||||
|
||||
#ifndef NUM_BUF_RANGES
|
||||
#define NUM_BUF_RANGES 15
|
||||
#endif
|
||||
|
||||
struct dsc_pps_rc_range {
|
||||
int range_min_qp;
|
||||
int range_max_qp;
|
||||
int range_bpg_offset;
|
||||
};
|
||||
|
||||
struct dsc_parameters {
|
||||
struct drm_dsc_config pps;
|
||||
|
||||
/* Additional parameters for register programming */
|
||||
uint32_t bytes_per_pixel; /* In u3.28 format */
|
||||
uint32_t rc_buffer_model_size;
|
||||
};
|
||||
|
||||
int dscc_compute_dsc_parameters(const struct drm_dsc_config *pps, struct dsc_parameters *dsc_params);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
706
drivers/gpu/drm/amd/display/dc/dsc/qp_tables.h
Normal file
706
drivers/gpu/drm/amd/display/dc/dsc/qp_tables.h
Normal file
@ -0,0 +1,706 @@
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
|
||||
|
||||
/*
|
||||
* Copyright 2017 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
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
const qp_table qp_table_422_10bpc_min = {
|
||||
{ 6, { 0, 4, 5, 6, 6, 6, 6, 7, 7, 8, 9, 9, 9, 12, 16} },
|
||||
{ 6.5, { 0, 4, 5, 6, 6, 6, 6, 7, 7, 8, 9, 9, 9, 12, 16} },
|
||||
{ 7, { 0, 4, 5, 6, 6, 6, 6, 7, 7, 7, 9, 9, 9, 11, 15} },
|
||||
{ 7.5, { 0, 2, 4, 6, 6, 6, 6, 7, 7, 7, 8, 9, 9, 11, 15} },
|
||||
{ 8, { 0, 2, 3, 5, 5, 6, 6, 7, 7, 7, 8, 8, 9, 11, 14} },
|
||||
{ 8.5, { 0, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8, 8, 9, 11, 14} },
|
||||
{ 9, { 0, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8, 8, 9, 11, 13} },
|
||||
{ 9.5, { 0, 2, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 11, 13} },
|
||||
{ 10, { 0, 2, 2, 3, 4, 5, 5, 6, 6, 7, 8, 8, 9, 11, 12} },
|
||||
{10.5, { 0, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 11, 12} },
|
||||
{ 11, { 0, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11} },
|
||||
{11.5, { 0, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 10, 11} },
|
||||
{ 12, { 0, 2, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 10} },
|
||||
{12.5, { 0, 1, 2, 2, 4, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10} },
|
||||
{ 13, { 0, 1, 2, 2, 4, 4, 4, 5, 5, 6, 6, 6, 8, 8, 9} },
|
||||
{13.5, { 0, 1, 2, 2, 3, 4, 4, 4, 5, 6, 6, 6, 7, 8, 9} },
|
||||
{ 14, { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 6, 7, 7, 8} },
|
||||
{14.5, { 0, 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8} },
|
||||
{ 15, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 6, 6, 6, 8} },
|
||||
{15.5, { 0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 7} },
|
||||
{ 16, { 0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 5, 5, 7} },
|
||||
{16.5, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6} },
|
||||
{ 17, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 6} },
|
||||
{17.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5} },
|
||||
{ 18, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 5} },
|
||||
{18.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 5} },
|
||||
{ 19, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 4} },
|
||||
{19.5, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 4} },
|
||||
{ 20, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 3} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_444_8bpc_max = {
|
||||
{ 6, { 4, 6, 8, 8, 9, 9, 9, 10, 11, 12, 12, 12, 12, 13, 15} },
|
||||
{ 6.5, { 4, 6, 7, 8, 8, 8, 9, 10, 11, 11, 12, 12, 12, 13, 15} },
|
||||
{ 7, { 4, 5, 7, 7, 8, 8, 8, 9, 10, 11, 11, 12, 12, 13, 14} },
|
||||
{ 7.5, { 4, 5, 6, 7, 7, 8, 8, 9, 10, 10, 11, 11, 12, 13, 14} },
|
||||
{ 8, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} },
|
||||
{ 8.5, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} },
|
||||
{ 9, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 13} },
|
||||
{ 9.5, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 13} },
|
||||
{ 10, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 12} },
|
||||
{10.5, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 10, 11, 12} },
|
||||
{ 11, { 2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 10, 10, 11} },
|
||||
{11.5, { 2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10, 11} },
|
||||
{ 12, { 2, 3, 4, 5, 6, 6, 7, 8, 8, 9, 9, 9, 9, 10, 11} },
|
||||
{12.5, { 2, 3, 4, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11} },
|
||||
{ 13, { 1, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 10} },
|
||||
{13.5, { 1, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10} },
|
||||
{ 14, { 1, 2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 8, 8, 8, 10} },
|
||||
{14.5, { 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9} },
|
||||
{ 15, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9} },
|
||||
{15.5, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9} },
|
||||
{ 16, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 8} },
|
||||
{16.5, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 8} },
|
||||
{ 17, { 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 8} },
|
||||
{17.5, { 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 8} },
|
||||
{ 18, { 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 7} },
|
||||
{18.5, { 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 7} },
|
||||
{ 19, { 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6} },
|
||||
{19.5, { 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6} },
|
||||
{ 20, { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 6} },
|
||||
{20.5, { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 6} },
|
||||
{ 21, { 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5} },
|
||||
{21.5, { 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5} },
|
||||
{ 22, { 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 5} },
|
||||
{22.5, { 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 4} },
|
||||
{ 23, { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4} },
|
||||
{23.5, { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4} },
|
||||
{ 24, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_420_12bpc_max = {
|
||||
{ 4, {11, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 21, 22} },
|
||||
{ 4.5, {10, 11, 12, 13, 14, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} },
|
||||
{ 5, { 9, 11, 12, 13, 14, 15, 15, 16, 17, 17, 18, 18, 19, 20, 21} },
|
||||
{ 5.5, { 8, 10, 11, 12, 13, 14, 15, 16, 16, 17, 17, 18, 18, 19, 20} },
|
||||
{ 6, { 6, 9, 11, 12, 13, 14, 15, 16, 16, 17, 17, 17, 17, 18, 19} },
|
||||
{ 6.5, { 6, 8, 10, 11, 11, 13, 14, 15, 15, 16, 16, 17, 17, 18, 19} },
|
||||
{ 7, { 5, 7, 9, 10, 10, 12, 13, 14, 14, 15, 16, 16, 17, 17, 18} },
|
||||
{ 7.5, { 5, 7, 8, 9, 9, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17} },
|
||||
{ 8, { 4, 6, 7, 8, 8, 10, 11, 12, 13, 13, 14, 15, 15, 16, 17} },
|
||||
{ 8.5, { 3, 6, 6, 7, 7, 10, 11, 12, 13, 13, 14, 14, 15, 15, 16} },
|
||||
{ 9, { 3, 5, 6, 7, 7, 10, 11, 12, 12, 13, 13, 14, 14, 14, 15} },
|
||||
{ 9.5, { 2, 5, 6, 6, 7, 9, 10, 11, 12, 12, 13, 13, 13, 14, 15} },
|
||||
{ 10, { 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, 13, 15} },
|
||||
{10.5, { 2, 3, 5, 5, 6, 7, 8, 9, 11, 11, 12, 12, 12, 12, 14} },
|
||||
{ 11, { 1, 3, 4, 5, 6, 6, 7, 9, 10, 11, 11, 11, 12, 12, 13} },
|
||||
{11.5, { 1, 2, 3, 4, 5, 6, 6, 8, 9, 10, 10, 11, 11, 11, 13} },
|
||||
{ 12, { 1, 1, 3, 3, 4, 5, 6, 7, 8, 9, 9, 10, 10, 10, 12} },
|
||||
{12.5, { 1, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 9, 10, 11} },
|
||||
{ 13, { 1, 1, 1, 2, 4, 4, 6, 6, 7, 8, 8, 9, 9, 9, 11} },
|
||||
{13.5, { 1, 1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 8, 8, 9, 11} },
|
||||
{ 14, { 1, 1, 1, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 8, 10} },
|
||||
{14.5, { 0, 1, 1, 1, 2, 3, 4, 4, 5, 5, 6, 7, 7, 7, 9} },
|
||||
{ 15, { 0, 1, 1, 1, 1, 2, 3, 3, 5, 5, 5, 6, 6, 7, 9} },
|
||||
{15.5, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 8} },
|
||||
{ 16, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 7} },
|
||||
{16.5, { 0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 4, 4, 5, 7} },
|
||||
{ 17, { 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 6} },
|
||||
{17.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 6} },
|
||||
{ 18, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 5} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_444_10bpc_min = {
|
||||
{ 6, { 0, 4, 7, 7, 9, 9, 9, 9, 9, 10, 10, 10, 10, 12, 18} },
|
||||
{ 6.5, { 0, 4, 6, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 12, 18} },
|
||||
{ 7, { 0, 4, 6, 6, 8, 8, 8, 8, 8, 9, 9, 10, 10, 12, 17} },
|
||||
{ 7.5, { 0, 4, 6, 6, 7, 8, 8, 8, 8, 8, 9, 9, 10, 12, 17} },
|
||||
{ 8, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 8, 9, 9, 9, 12, 16} },
|
||||
{ 8.5, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 8, 9, 9, 9, 12, 16} },
|
||||
{ 9, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} },
|
||||
{ 9.5, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} },
|
||||
{ 10, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 15} },
|
||||
{10.5, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 15} },
|
||||
{ 11, { 0, 3, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 14} },
|
||||
{11.5, { 0, 3, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 14} },
|
||||
{ 12, { 0, 2, 4, 4, 6, 6, 7, 7, 7, 7, 9, 9, 9, 11, 14} },
|
||||
{12.5, { 0, 2, 4, 4, 6, 6, 7, 7, 7, 7, 8, 9, 9, 11, 14} },
|
||||
{ 13, { 0, 2, 4, 4, 5, 6, 7, 7, 7, 7, 8, 9, 9, 11, 13} },
|
||||
{13.5, { 0, 2, 3, 4, 5, 6, 6, 7, 7, 7, 8, 9, 9, 11, 13} },
|
||||
{ 14, { 0, 2, 3, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 11, 13} },
|
||||
{14.5, { 0, 2, 3, 4, 5, 5, 6, 6, 6, 7, 7, 8, 9, 11, 12} },
|
||||
{ 15, { 0, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 9, 11, 12} },
|
||||
{15.5, { 0, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 9, 11, 12} },
|
||||
{ 16, { 0, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 8, 10, 11} },
|
||||
{16.5, { 0, 1, 2, 3, 4, 5, 5, 6, 6, 6, 7, 8, 8, 10, 11} },
|
||||
{ 17, { 0, 1, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 8, 9, 11} },
|
||||
{17.5, { 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 11} },
|
||||
{ 18, { 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10} },
|
||||
{18.5, { 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10} },
|
||||
{ 19, { 0, 1, 1, 2, 3, 3, 3, 4, 5, 6, 6, 7, 7, 8, 9} },
|
||||
{19.5, { 0, 1, 1, 2, 3, 3, 3, 4, 5, 6, 6, 7, 7, 8, 9} },
|
||||
{ 20, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 9} },
|
||||
{20.5, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 9} },
|
||||
{ 21, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 6, 6, 7, 9} },
|
||||
{21.5, { 0, 1, 1, 2, 2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 8} },
|
||||
{ 22, { 0, 0, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 8} },
|
||||
{22.5, { 0, 0, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 7} },
|
||||
{ 23, { 0, 0, 1, 2, 2, 2, 3, 3, 3, 3, 5, 5, 5, 5, 7} },
|
||||
{23.5, { 0, 0, 0, 2, 2, 2, 3, 3, 3, 3, 5, 5, 5, 5, 7} },
|
||||
{ 24, { 0, 0, 0, 1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 7} },
|
||||
{24.5, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 7} },
|
||||
{ 25, { 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 6} },
|
||||
{25.5, { 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 6} },
|
||||
{ 26, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 5} },
|
||||
{26.5, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 5} },
|
||||
{ 27, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 5} },
|
||||
{27.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 5} },
|
||||
{ 28, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 4} },
|
||||
{28.5, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 4} },
|
||||
{ 29, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3} },
|
||||
{29.5, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3} },
|
||||
{ 30, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_420_8bpc_max = {
|
||||
{ 4, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 13, 14} },
|
||||
{ 4.5, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} },
|
||||
{ 5, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 12, 13} },
|
||||
{ 5.5, { 3, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12} },
|
||||
{ 6, { 2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10, 11} },
|
||||
{ 6.5, { 2, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11} },
|
||||
{ 7, { 1, 2, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 9, 10} },
|
||||
{ 7.5, { 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 8, 9} },
|
||||
{ 8, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9} },
|
||||
{ 8.5, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8} },
|
||||
{ 9, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7} },
|
||||
{ 9.5, { 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 7} },
|
||||
{ 10, { 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6} },
|
||||
{10.5, { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 6} },
|
||||
{ 11, { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5} },
|
||||
{11.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5} },
|
||||
{ 12, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 4} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_444_8bpc_min = {
|
||||
{ 6, { 0, 1, 3, 3, 5, 5, 5, 5, 5, 6, 6, 6, 6, 9, 14} },
|
||||
{ 6.5, { 0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 9, 14} },
|
||||
{ 7, { 0, 0, 2, 2, 4, 4, 4, 4, 4, 5, 5, 6, 6, 9, 13} },
|
||||
{ 7.5, { 0, 0, 2, 2, 3, 4, 4, 4, 4, 4, 5, 5, 6, 9, 13} },
|
||||
{ 8, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 4, 5, 5, 5, 8, 12} },
|
||||
{ 8.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 4, 5, 5, 5, 8, 12} },
|
||||
{ 9, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 12} },
|
||||
{ 9.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 12} },
|
||||
{ 10, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} },
|
||||
{10.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} },
|
||||
{ 11, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10} },
|
||||
{11.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10} },
|
||||
{ 12, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10} },
|
||||
{12.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 4, 5, 5, 7, 10} },
|
||||
{ 13, { 0, 0, 1, 1, 2, 3, 3, 3, 3, 3, 4, 5, 5, 7, 9} },
|
||||
{13.5, { 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 4, 5, 5, 7, 9} },
|
||||
{ 14, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 4, 5, 5, 7, 9} },
|
||||
{14.5, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 4, 4, 5, 7, 8} },
|
||||
{ 15, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 8} },
|
||||
{15.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 8} },
|
||||
{ 16, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7} },
|
||||
{16.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7} },
|
||||
{ 17, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7} },
|
||||
{17.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7} },
|
||||
{ 18, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6} },
|
||||
{18.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6} },
|
||||
{ 19, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5} },
|
||||
{19.5, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5} },
|
||||
{ 20, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 3, 5} },
|
||||
{20.5, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 3, 5} },
|
||||
{ 21, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4} },
|
||||
{21.5, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4} },
|
||||
{ 22, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 4} },
|
||||
{22.5, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3} },
|
||||
{ 23, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3} },
|
||||
{23.5, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3} },
|
||||
{ 24, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_444_12bpc_min = {
|
||||
{ 6, { 0, 5, 11, 11, 13, 13, 13, 13, 13, 14, 14, 14, 14, 17, 22} },
|
||||
{ 6.5, { 0, 5, 10, 11, 12, 12, 13, 13, 13, 13, 14, 14, 14, 17, 22} },
|
||||
{ 7, { 0, 5, 10, 10, 12, 12, 12, 12, 12, 13, 13, 14, 14, 17, 21} },
|
||||
{ 7.5, { 0, 5, 9, 10, 11, 12, 12, 12, 12, 12, 13, 13, 14, 17, 21} },
|
||||
{ 8, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 12, 13, 13, 13, 16, 20} },
|
||||
{ 8.5, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 12, 13, 13, 13, 16, 20} },
|
||||
{ 9, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} },
|
||||
{ 9.5, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} },
|
||||
{ 10, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} },
|
||||
{10.5, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} },
|
||||
{ 11, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} },
|
||||
{11.5, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} },
|
||||
{ 12, { 0, 4, 7, 8, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} },
|
||||
{12.5, { 0, 4, 7, 8, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} },
|
||||
{ 13, { 0, 4, 7, 8, 9, 11, 11, 11, 11, 11, 13, 13, 13, 15, 17} },
|
||||
{13.5, { 0, 3, 6, 7, 9, 10, 10, 11, 11, 11, 12, 13, 13, 15, 17} },
|
||||
{ 14, { 0, 3, 5, 6, 9, 9, 9, 10, 11, 11, 12, 13, 13, 15, 17} },
|
||||
{14.5, { 0, 2, 5, 6, 8, 9, 9, 10, 11, 11, 12, 13, 13, 15, 16} },
|
||||
{ 15, { 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 12, 13, 13, 15, 16} },
|
||||
{15.5, { 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 12, 13, 13, 15, 16} },
|
||||
{ 16, { 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 11, 12, 12, 14, 15} },
|
||||
{16.5, { 0, 2, 3, 5, 7, 8, 9, 10, 11, 11, 11, 12, 12, 14, 15} },
|
||||
{ 17, { 0, 2, 3, 5, 5, 6, 9, 9, 10, 10, 11, 11, 12, 13, 15} },
|
||||
{17.5, { 0, 2, 3, 5, 5, 6, 8, 9, 10, 10, 11, 11, 12, 13, 15} },
|
||||
{ 18, { 0, 2, 3, 5, 5, 6, 8, 9, 10, 10, 11, 11, 12, 13, 14} },
|
||||
{18.5, { 0, 2, 3, 5, 5, 6, 8, 9, 10, 10, 11, 11, 12, 13, 14} },
|
||||
{ 19, { 0, 1, 2, 4, 5, 5, 7, 8, 9, 9, 10, 11, 11, 12, 13} },
|
||||
{19.5, { 0, 1, 2, 4, 5, 5, 7, 8, 9, 9, 10, 11, 11, 12, 13} },
|
||||
{ 20, { 0, 1, 2, 3, 4, 5, 7, 8, 8, 8, 9, 10, 10, 11, 13} },
|
||||
{20.5, { 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11, 13} },
|
||||
{ 21, { 0, 1, 2, 3, 4, 5, 5, 7, 7, 8, 9, 10, 10, 11, 13} },
|
||||
{21.5, { 0, 1, 2, 3, 3, 4, 5, 7, 7, 8, 9, 10, 10, 11, 12} },
|
||||
{ 22, { 0, 0, 1, 3, 3, 4, 5, 6, 7, 8, 9, 9, 9, 10, 12} },
|
||||
{22.5, { 0, 0, 1, 3, 3, 4, 5, 6, 7, 8, 9, 9, 9, 10, 11} },
|
||||
{ 23, { 0, 0, 1, 3, 3, 4, 5, 6, 6, 7, 9, 9, 9, 9, 11} },
|
||||
{23.5, { 0, 0, 1, 3, 3, 4, 5, 6, 6, 7, 9, 9, 9, 9, 11} },
|
||||
{ 24, { 0, 0, 1, 2, 3, 4, 5, 6, 6, 7, 8, 8, 8, 9, 11} },
|
||||
{24.5, { 0, 0, 1, 2, 3, 4, 4, 6, 6, 7, 8, 8, 8, 9, 11} },
|
||||
{ 25, { 0, 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 8, 8, 8, 10} },
|
||||
{25.5, { 0, 0, 1, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 8, 10} },
|
||||
{ 26, { 0, 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 7, 7, 9} },
|
||||
{26.5, { 0, 0, 1, 2, 2, 3, 4, 5, 5, 5, 7, 7, 7, 7, 9} },
|
||||
{ 27, { 0, 0, 1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 7, 9} },
|
||||
{27.5, { 0, 0, 1, 1, 2, 2, 4, 4, 4, 5, 6, 7, 7, 7, 9} },
|
||||
{ 28, { 0, 0, 0, 1, 1, 2, 3, 4, 4, 4, 6, 6, 6, 7, 9} },
|
||||
{28.5, { 0, 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 6, 8} },
|
||||
{ 29, { 0, 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8} },
|
||||
{29.5, { 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 6, 7} },
|
||||
{ 30, { 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 5, 5, 5, 5, 7} },
|
||||
{30.5, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 4, 5, 7} },
|
||||
{ 31, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 4, 5, 7} },
|
||||
{31.5, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7} },
|
||||
{ 32, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 4, 6} },
|
||||
{32.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 6} },
|
||||
{ 33, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 5} },
|
||||
{33.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 5} },
|
||||
{ 34, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 5} },
|
||||
{34.5, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 5} },
|
||||
{ 35, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 4} },
|
||||
{35.5, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 4} },
|
||||
{ 36, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_420_12bpc_min = {
|
||||
{ 4, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 21} },
|
||||
{ 4.5, { 0, 4, 8, 9, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} },
|
||||
{ 5, { 0, 4, 8, 9, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} },
|
||||
{ 5.5, { 0, 4, 7, 8, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} },
|
||||
{ 6, { 0, 4, 7, 8, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} },
|
||||
{ 6.5, { 0, 4, 6, 8, 9, 10, 11, 11, 11, 11, 13, 13, 13, 15, 18} },
|
||||
{ 7, { 0, 3, 5, 7, 9, 10, 10, 11, 11, 11, 13, 13, 13, 15, 17} },
|
||||
{ 7.5, { 0, 3, 5, 7, 8, 9, 10, 10, 11, 11, 12, 13, 13, 15, 16} },
|
||||
{ 8, { 0, 2, 4, 6, 7, 9, 9, 10, 11, 11, 12, 13, 13, 15, 16} },
|
||||
{ 8.5, { 0, 2, 4, 6, 6, 9, 9, 10, 11, 11, 12, 12, 13, 14, 15} },
|
||||
{ 9, { 0, 2, 4, 6, 6, 9, 9, 10, 10, 11, 11, 12, 13, 13, 14} },
|
||||
{ 9.5, { 0, 2, 4, 5, 6, 8, 8, 9, 10, 10, 11, 12, 12, 13, 14} },
|
||||
{ 10, { 0, 2, 3, 5, 6, 7, 8, 8, 9, 10, 10, 12, 12, 12, 14} },
|
||||
{10.5, { 0, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 11, 11, 13} },
|
||||
{ 11, { 0, 2, 3, 4, 5, 5, 6, 8, 8, 9, 9, 10, 11, 11, 12} },
|
||||
{11.5, { 0, 1, 2, 3, 4, 5, 5, 7, 8, 8, 9, 10, 10, 10, 12} },
|
||||
{ 12, { 0, 0, 2, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 9, 11} },
|
||||
{12.5, { 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 8, 8, 9, 10} },
|
||||
{ 13, { 0, 0, 0, 1, 3, 3, 5, 5, 6, 7, 7, 8, 8, 8, 10} },
|
||||
{13.5, { 0, 0, 0, 1, 2, 3, 4, 4, 5, 6, 7, 7, 7, 8, 10} },
|
||||
{ 14, { 0, 0, 0, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 7, 9} },
|
||||
{14.5, { 0, 0, 0, 0, 1, 2, 3, 3, 4, 4, 5, 6, 6, 6, 8} },
|
||||
{ 15, { 0, 0, 0, 0, 0, 1, 2, 2, 4, 4, 4, 5, 5, 6, 8} },
|
||||
{15.5, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7} },
|
||||
{ 16, { 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 6} },
|
||||
{16.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 6} },
|
||||
{ 17, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 5} },
|
||||
{17.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 3, 5} },
|
||||
{ 18, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 4} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_422_12bpc_min = {
|
||||
{ 6, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 16, 20} },
|
||||
{ 6.5, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 16, 20} },
|
||||
{ 7, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} },
|
||||
{ 7.5, { 0, 4, 8, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} },
|
||||
{ 8, { 0, 4, 7, 8, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} },
|
||||
{ 8.5, { 0, 3, 6, 8, 9, 10, 10, 11, 11, 11, 12, 13, 13, 15, 18} },
|
||||
{ 9, { 0, 3, 5, 8, 9, 10, 10, 10, 11, 11, 12, 13, 13, 15, 17} },
|
||||
{ 9.5, { 0, 3, 5, 7, 8, 9, 10, 10, 11, 11, 12, 13, 13, 15, 17} },
|
||||
{ 10, { 0, 2, 4, 6, 7, 9, 9, 10, 11, 11, 12, 13, 13, 15, 16} },
|
||||
{10.5, { 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 12, 13, 13, 15, 16} },
|
||||
{ 11, { 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 14, 15} },
|
||||
{11.5, { 0, 2, 4, 6, 7, 7, 9, 9, 10, 11, 11, 12, 12, 14, 15} },
|
||||
{ 12, { 0, 2, 4, 6, 6, 6, 8, 8, 9, 9, 11, 11, 12, 13, 14} },
|
||||
{12.5, { 0, 1, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11, 11, 13, 14} },
|
||||
{ 13, { 0, 1, 3, 4, 5, 5, 7, 8, 8, 9, 10, 10, 11, 12, 13} },
|
||||
{13.5, { 0, 1, 3, 3, 4, 5, 7, 7, 8, 8, 10, 10, 10, 12, 13} },
|
||||
{ 14, { 0, 0, 2, 3, 4, 5, 6, 6, 7, 7, 9, 10, 10, 11, 12} },
|
||||
{14.5, { 0, 0, 1, 3, 4, 4, 6, 6, 6, 7, 9, 9, 9, 11, 12} },
|
||||
{ 15, { 0, 0, 1, 3, 3, 4, 5, 6, 6, 6, 8, 9, 9, 10, 12} },
|
||||
{15.5, { 0, 0, 1, 2, 3, 4, 5, 5, 6, 6, 8, 8, 8, 10, 11} },
|
||||
{ 16, { 0, 0, 1, 2, 3, 4, 5, 5, 6, 6, 8, 8, 8, 9, 11} },
|
||||
{16.5, { 0, 0, 0, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 9, 10} },
|
||||
{ 17, { 0, 0, 0, 1, 2, 2, 4, 4, 4, 5, 6, 6, 6, 8, 10} },
|
||||
{17.5, { 0, 0, 0, 1, 2, 2, 3, 4, 4, 4, 5, 6, 6, 8, 9} },
|
||||
{ 18, { 0, 0, 0, 1, 2, 2, 3, 3, 3, 4, 5, 5, 6, 7, 9} },
|
||||
{18.5, { 0, 0, 0, 1, 2, 2, 3, 3, 3, 3, 5, 5, 5, 7, 9} },
|
||||
{ 19, { 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 8} },
|
||||
{19.5, { 0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 6, 8} },
|
||||
{ 20, { 0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 7} },
|
||||
{20.5, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 7} },
|
||||
{ 21, { 0, 0, 0, 0, 0, 1, 2, 2, 3, 3, 3, 4, 4, 4, 6} },
|
||||
{21.5, { 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 6} },
|
||||
{ 22, { 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 6} },
|
||||
{22.5, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 5} },
|
||||
{ 23, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 5} },
|
||||
{23.5, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 4} },
|
||||
{ 24, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 4} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_422_12bpc_max = {
|
||||
{ 6, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} },
|
||||
{ 6.5, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} },
|
||||
{ 7, {11, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 19, 19, 20} },
|
||||
{ 7.5, { 9, 10, 12, 14, 15, 15, 15, 16, 16, 17, 17, 18, 18, 19, 20} },
|
||||
{ 8, { 6, 9, 10, 12, 14, 15, 15, 16, 16, 17, 17, 17, 17, 18, 19} },
|
||||
{ 8.5, { 6, 8, 9, 11, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 19} },
|
||||
{ 9, { 5, 7, 8, 10, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 18} },
|
||||
{ 9.5, { 5, 7, 7, 9, 10, 12, 12, 13, 14, 14, 15, 15, 16, 17, 18} },
|
||||
{ 10, { 4, 6, 6, 8, 9, 11, 11, 12, 13, 13, 14, 15, 15, 16, 17} },
|
||||
{10.5, { 4, 6, 6, 8, 9, 10, 11, 12, 13, 13, 14, 15, 15, 16, 17} },
|
||||
{ 11, { 4, 5, 6, 8, 9, 10, 11, 12, 13, 13, 14, 14, 15, 15, 16} },
|
||||
{11.5, { 3, 5, 6, 8, 9, 9, 11, 11, 12, 13, 13, 14, 14, 15, 16} },
|
||||
{ 12, { 3, 5, 6, 8, 8, 8, 10, 10, 11, 11, 13, 13, 14, 14, 15} },
|
||||
{12.5, { 3, 4, 6, 7, 8, 8, 9, 10, 10, 11, 12, 13, 13, 14, 15} },
|
||||
{ 13, { 2, 4, 5, 6, 7, 7, 9, 10, 10, 11, 12, 12, 13, 13, 14} },
|
||||
{13.5, { 2, 4, 5, 5, 6, 7, 9, 9, 10, 10, 12, 12, 12, 13, 14} },
|
||||
{ 14, { 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 11, 12, 12, 12, 13} },
|
||||
{14.5, { 2, 3, 3, 5, 6, 6, 8, 8, 8, 9, 11, 11, 11, 12, 13} },
|
||||
{ 15, { 2, 3, 3, 5, 5, 6, 7, 8, 8, 8, 10, 11, 11, 11, 13} },
|
||||
{15.5, { 2, 2, 3, 4, 5, 6, 7, 7, 8, 8, 10, 10, 10, 11, 12} },
|
||||
{ 16, { 2, 2, 3, 4, 5, 6, 7, 7, 8, 8, 10, 10, 10, 10, 12} },
|
||||
{16.5, { 1, 2, 2, 4, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 11} },
|
||||
{ 17, { 1, 1, 2, 3, 4, 4, 6, 6, 6, 7, 8, 8, 8, 9, 11} },
|
||||
{17.5, { 1, 1, 2, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8, 9, 10} },
|
||||
{ 18, { 1, 1, 1, 2, 3, 3, 5, 5, 5, 6, 7, 7, 8, 8, 10} },
|
||||
{18.5, { 1, 1, 1, 2, 3, 3, 5, 5, 5, 5, 7, 7, 7, 8, 10} },
|
||||
{ 19, { 1, 1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 7, 9} },
|
||||
{19.5, { 1, 1, 1, 2, 2, 2, 4, 5, 5, 5, 6, 6, 6, 7, 9} },
|
||||
{ 20, { 1, 1, 1, 2, 2, 2, 4, 5, 5, 5, 6, 6, 6, 6, 8} },
|
||||
{20.5, { 0, 0, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 8} },
|
||||
{ 21, { 0, 0, 0, 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 5, 7} },
|
||||
{21.5, { 0, 0, 0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 7} },
|
||||
{ 22, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 7} },
|
||||
{22.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 6} },
|
||||
{ 23, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 6} },
|
||||
{23.5, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 5} },
|
||||
{ 24, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 5} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_444_12bpc_max = {
|
||||
{ 6, {12, 14, 16, 16, 17, 17, 17, 18, 19, 20, 20, 20, 20, 21, 23} },
|
||||
{ 6.5, {12, 14, 15, 16, 16, 16, 17, 18, 19, 19, 20, 20, 20, 21, 23} },
|
||||
{ 7, {12, 13, 15, 15, 16, 16, 16, 17, 18, 19, 19, 20, 20, 21, 22} },
|
||||
{ 7.5, {12, 13, 14, 15, 15, 16, 16, 17, 18, 18, 19, 19, 20, 21, 22} },
|
||||
{ 8, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} },
|
||||
{ 8.5, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} },
|
||||
{ 9, {11, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 19, 19, 21} },
|
||||
{ 9.5, {11, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 19, 19, 21} },
|
||||
{ 10, {11, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 19, 19, 20} },
|
||||
{10.5, {10, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 18, 19, 20} },
|
||||
{ 11, { 9, 11, 13, 14, 15, 15, 15, 16, 16, 17, 17, 17, 18, 18, 19} },
|
||||
{11.5, { 9, 11, 13, 14, 15, 15, 15, 16, 16, 17, 17, 17, 17, 18, 19} },
|
||||
{ 12, { 6, 9, 12, 13, 14, 14, 15, 16, 16, 17, 17, 17, 17, 18, 19} },
|
||||
{12.5, { 6, 9, 12, 13, 14, 14, 14, 15, 15, 16, 16, 17, 17, 18, 19} },
|
||||
{ 13, { 5, 9, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 17, 18} },
|
||||
{13.5, { 5, 8, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 18} },
|
||||
{ 14, { 5, 8, 10, 11, 12, 12, 12, 13, 14, 14, 15, 16, 16, 16, 18} },
|
||||
{14.5, { 4, 7, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 17} },
|
||||
{ 15, { 4, 7, 9, 10, 10, 11, 11, 12, 13, 13, 14, 15, 15, 16, 17} },
|
||||
{15.5, { 4, 7, 9, 10, 10, 11, 11, 12, 13, 13, 14, 15, 15, 16, 17} },
|
||||
{ 16, { 4, 7, 9, 10, 10, 11, 11, 12, 13, 13, 13, 14, 14, 15, 16} },
|
||||
{16.5, { 4, 5, 7, 8, 10, 11, 11, 12, 13, 13, 13, 14, 14, 15, 16} },
|
||||
{ 17, { 4, 5, 7, 8, 8, 9, 11, 11, 12, 12, 12, 13, 13, 14, 16} },
|
||||
{17.5, { 3, 5, 7, 8, 8, 9, 10, 11, 12, 12, 12, 13, 13, 14, 16} },
|
||||
{ 18, { 3, 5, 7, 8, 8, 9, 10, 11, 12, 12, 12, 13, 13, 14, 15} },
|
||||
{18.5, { 3, 5, 7, 8, 8, 9, 10, 11, 12, 12, 12, 13, 13, 14, 15} },
|
||||
{ 19, { 3, 4, 6, 7, 8, 8, 9, 10, 11, 11, 11, 12, 12, 13, 14} },
|
||||
{19.5, { 3, 4, 6, 7, 8, 8, 9, 10, 11, 11, 11, 12, 12, 13, 14} },
|
||||
{ 20, { 2, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11, 11, 12, 14} },
|
||||
{20.5, { 2, 3, 5, 5, 7, 8, 8, 8, 9, 10, 10, 11, 11, 12, 14} },
|
||||
{ 21, { 2, 3, 5, 5, 7, 7, 7, 8, 8, 9, 10, 11, 11, 12, 14} },
|
||||
{21.5, { 2, 3, 5, 5, 6, 6, 7, 8, 8, 9, 10, 11, 11, 12, 13} },
|
||||
{ 22, { 2, 2, 4, 5, 6, 6, 7, 7, 8, 9, 10, 10, 10, 11, 13} },
|
||||
{22.5, { 2, 2, 4, 5, 5, 6, 7, 7, 8, 9, 10, 10, 10, 11, 12} },
|
||||
{ 23, { 2, 2, 4, 5, 5, 6, 7, 7, 7, 8, 10, 10, 10, 10, 12} },
|
||||
{23.5, { 2, 2, 3, 5, 5, 6, 7, 7, 7, 8, 10, 10, 10, 10, 12} },
|
||||
{ 24, { 2, 2, 3, 4, 4, 5, 7, 7, 7, 8, 9, 9, 9, 10, 12} },
|
||||
{24.5, { 1, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 9, 9, 10, 12} },
|
||||
{ 25, { 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 9, 9, 11} },
|
||||
{25.5, { 1, 1, 3, 3, 4, 5, 6, 6, 7, 7, 8, 9, 9, 9, 11} },
|
||||
{ 26, { 1, 1, 3, 3, 3, 4, 5, 6, 6, 7, 8, 8, 8, 8, 10} },
|
||||
{26.5, { 1, 1, 2, 3, 3, 4, 5, 6, 6, 6, 8, 8, 8, 8, 10} },
|
||||
{ 27, { 1, 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8, 8, 8, 10} },
|
||||
{27.5, { 1, 1, 2, 2, 3, 3, 5, 5, 5, 6, 7, 8, 8, 8, 10} },
|
||||
{ 28, { 0, 1, 1, 2, 2, 3, 4, 5, 5, 5, 7, 7, 7, 8, 10} },
|
||||
{28.5, { 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 7, 9} },
|
||||
{ 29, { 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 9} },
|
||||
{29.5, { 0, 1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 6, 7, 7, 8} },
|
||||
{ 30, { 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 6, 6, 6, 6, 8} },
|
||||
{30.5, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6, 8} },
|
||||
{ 31, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6, 8} },
|
||||
{31.5, { 0, 0, 0, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 8} },
|
||||
{ 32, { 0, 0, 0, 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 7} },
|
||||
{32.5, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 4, 4, 4, 5, 7} },
|
||||
{ 33, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 6} },
|
||||
{33.5, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 6} },
|
||||
{ 34, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 6} },
|
||||
{34.5, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 3, 3, 3, 3, 4, 6} },
|
||||
{ 35, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 5} },
|
||||
{35.5, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 5} },
|
||||
{ 36, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 4} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_420_8bpc_min = {
|
||||
{ 4, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 9, 13} },
|
||||
{ 4.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} },
|
||||
{ 5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} },
|
||||
{ 5.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} },
|
||||
{ 6, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10} },
|
||||
{ 6.5, { 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 4, 5, 5, 7, 10} },
|
||||
{ 7, { 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 4, 5, 5, 7, 9} },
|
||||
{ 7.5, { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 4, 4, 5, 7, 8} },
|
||||
{ 8, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 8} },
|
||||
{ 8.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7} },
|
||||
{ 9, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6} },
|
||||
{ 9.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6} },
|
||||
{ 10, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5} },
|
||||
{10.5, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 5} },
|
||||
{ 11, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4} },
|
||||
{11.5, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4} },
|
||||
{ 12, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 3} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_422_8bpc_min = {
|
||||
{ 6, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} },
|
||||
{ 6.5, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} },
|
||||
{ 7, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} },
|
||||
{ 7.5, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} },
|
||||
{ 8, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10} },
|
||||
{ 8.5, { 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 4, 5, 5, 7, 10} },
|
||||
{ 9, { 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 4, 5, 5, 7, 9} },
|
||||
{ 9.5, { 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 9} },
|
||||
{ 10, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 8} },
|
||||
{10.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 8} },
|
||||
{ 11, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7} },
|
||||
{11.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7} },
|
||||
{ 12, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6} },
|
||||
{12.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6} },
|
||||
{ 13, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5} },
|
||||
{13.5, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 4, 5} },
|
||||
{ 14, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4} },
|
||||
{14.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 4} },
|
||||
{ 15, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 4} },
|
||||
{15.5, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3} },
|
||||
{ 16, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_422_10bpc_max = {
|
||||
{ 6, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} },
|
||||
{ 6.5, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} },
|
||||
{ 7, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16} },
|
||||
{ 7.5, { 5, 6, 8, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16} },
|
||||
{ 8, { 4, 6, 7, 9, 10, 11, 11, 12, 12, 13, 13, 13, 13, 14, 15} },
|
||||
{ 8.5, { 4, 5, 6, 8, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15} },
|
||||
{ 9, { 3, 4, 5, 7, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14} },
|
||||
{ 9.5, { 3, 4, 4, 6, 6, 8, 8, 9, 10, 10, 11, 11, 12, 13, 14} },
|
||||
{ 10, { 2, 3, 3, 5, 5, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13} },
|
||||
{10.5, { 2, 3, 3, 5, 5, 6, 7, 8, 9, 9, 10, 11, 11, 12, 13} },
|
||||
{ 11, { 2, 3, 3, 5, 5, 6, 7, 8, 9, 9, 10, 10, 11, 11, 12} },
|
||||
{11.5, { 2, 3, 3, 5, 5, 5, 7, 7, 8, 9, 9, 10, 10, 11, 12} },
|
||||
{ 12, { 2, 3, 3, 5, 5, 5, 7, 7, 8, 8, 9, 9, 10, 10, 11} },
|
||||
{12.5, { 2, 2, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 10, 11} },
|
||||
{ 13, { 1, 2, 3, 4, 5, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10} },
|
||||
{13.5, { 1, 2, 3, 3, 4, 5, 6, 6, 7, 7, 8, 8, 8, 9, 10} },
|
||||
{ 14, { 1, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 8, 8, 8, 9} },
|
||||
{14.5, { 1, 2, 2, 3, 4, 4, 5, 5, 5, 6, 7, 7, 7, 8, 9} },
|
||||
{ 15, { 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 7, 7, 7, 9} },
|
||||
{15.5, { 1, 1, 2, 2, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 8} },
|
||||
{ 16, { 1, 1, 2, 2, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 8} },
|
||||
{16.5, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7} },
|
||||
{ 17, { 0, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 7} },
|
||||
{17.5, { 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6} },
|
||||
{ 18, { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 6} },
|
||||
{18.5, { 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 6} },
|
||||
{ 19, { 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 5} },
|
||||
{19.5, { 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 5} },
|
||||
{ 20, { 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 4} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_420_10bpc_max = {
|
||||
{ 4, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 17, 18} },
|
||||
{ 4.5, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} },
|
||||
{ 5, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 16, 17} },
|
||||
{ 5.5, { 6, 7, 8, 9, 10, 10, 11, 12, 12, 13, 13, 14, 14, 15, 16} },
|
||||
{ 6, { 4, 6, 8, 9, 10, 10, 11, 12, 12, 13, 13, 13, 13, 14, 15} },
|
||||
{ 6.5, { 4, 5, 7, 8, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 15} },
|
||||
{ 7, { 3, 4, 6, 7, 7, 8, 9, 10, 10, 11, 12, 12, 13, 13, 14} },
|
||||
{ 7.5, { 3, 4, 5, 6, 6, 7, 8, 9, 10, 10, 11, 11, 12, 12, 13} },
|
||||
{ 8, { 2, 3, 4, 5, 5, 6, 7, 8, 9, 9, 10, 11, 11, 12, 13} },
|
||||
{ 8.5, { 1, 3, 3, 4, 4, 6, 7, 8, 9, 9, 10, 10, 11, 11, 12} },
|
||||
{ 9, { 1, 3, 3, 4, 4, 6, 7, 8, 8, 9, 9, 10, 10, 10, 11} },
|
||||
{ 9.5, { 1, 3, 3, 3, 4, 5, 6, 7, 8, 8, 9, 9, 9, 10, 11} },
|
||||
{ 10, { 1, 2, 3, 3, 4, 4, 5, 6, 7, 8, 8, 9, 9, 9, 11} },
|
||||
{10.5, { 1, 1, 3, 3, 3, 4, 5, 5, 7, 7, 8, 8, 8, 8, 10} },
|
||||
{ 11, { 0, 1, 2, 3, 3, 3, 4, 5, 6, 7, 7, 7, 8, 8, 9} },
|
||||
{11.5, { 0, 1, 1, 2, 3, 3, 3, 4, 5, 6, 6, 7, 7, 7, 9} },
|
||||
{ 12, { 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 6, 8} },
|
||||
{12.5, { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 7} },
|
||||
{ 13, { 0, 0, 0, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 7} },
|
||||
{13.5, { 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 6} },
|
||||
{ 14, { 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 6} },
|
||||
{14.5, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 5} },
|
||||
{ 15, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 5} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_420_10bpc_min = {
|
||||
{ 4, { 0, 4, 4, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 13, 17} },
|
||||
{ 4.5, { 0, 4, 4, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} },
|
||||
{ 5, { 0, 4, 4, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} },
|
||||
{ 5.5, { 0, 3, 3, 4, 6, 7, 7, 7, 7, 7, 9, 9, 9, 11, 15} },
|
||||
{ 6, { 0, 2, 3, 4, 6, 7, 7, 7, 7, 7, 9, 9, 9, 11, 14} },
|
||||
{ 6.5, { 0, 2, 3, 4, 5, 6, 6, 7, 7, 7, 8, 9, 9, 11, 14} },
|
||||
{ 7, { 0, 2, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 11, 13} },
|
||||
{ 7.5, { 0, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 11, 12} },
|
||||
{ 8, { 0, 2, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 11, 12} },
|
||||
{ 8.5, { 0, 2, 2, 3, 3, 5, 5, 6, 6, 7, 8, 8, 9, 10, 11} },
|
||||
{ 9, { 0, 2, 2, 3, 3, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10} },
|
||||
{ 9.5, { 0, 2, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10} },
|
||||
{ 10, { 0, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 8, 8, 8, 10} },
|
||||
{10.5, { 0, 0, 2, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 7, 9} },
|
||||
{ 11, { 0, 0, 1, 2, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8} },
|
||||
{11.5, { 0, 0, 0, 1, 2, 2, 2, 3, 4, 4, 5, 6, 6, 6, 8} },
|
||||
{ 12, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5, 7} },
|
||||
{12.5, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 6} },
|
||||
{ 13, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 6} },
|
||||
{13.5, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 5} },
|
||||
{ 14, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 5} },
|
||||
{14.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 4} },
|
||||
{ 15, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 4} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_444_10bpc_max = {
|
||||
{ 6, { 8, 10, 12, 12, 13, 13, 13, 14, 15, 16, 16, 16, 16, 17, 19} },
|
||||
{ 6.5, { 8, 10, 11, 12, 12, 12, 13, 14, 15, 15, 16, 16, 16, 17, 19} },
|
||||
{ 7, { 8, 9, 11, 11, 12, 12, 12, 13, 14, 15, 15, 16, 16, 17, 18} },
|
||||
{ 7.5, { 8, 9, 10, 11, 11, 12, 12, 13, 14, 14, 15, 15, 16, 17, 18} },
|
||||
{ 8, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} },
|
||||
{ 8.5, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} },
|
||||
{ 9, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 17} },
|
||||
{ 9.5, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 17} },
|
||||
{ 10, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16} },
|
||||
{10.5, { 6, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 14, 15, 16} },
|
||||
{ 11, { 5, 7, 9, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15} },
|
||||
{11.5, { 5, 7, 9, 10, 11, 11, 11, 12, 12, 13, 13, 13, 13, 14, 15} },
|
||||
{ 12, { 4, 6, 8, 9, 10, 10, 11, 12, 12, 13, 13, 13, 13, 14, 15} },
|
||||
{12.5, { 4, 6, 8, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15} },
|
||||
{ 13, { 3, 6, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 14} },
|
||||
{13.5, { 3, 5, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14} },
|
||||
{ 14, { 3, 5, 6, 7, 8, 8, 8, 9, 10, 10, 11, 12, 12, 12, 14} },
|
||||
{14.5, { 2, 4, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 13} },
|
||||
{ 15, { 2, 4, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13} },
|
||||
{15.5, { 2, 4, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13} },
|
||||
{ 16, { 2, 4, 5, 6, 6, 7, 7, 8, 9, 9, 9, 10, 10, 11, 12} },
|
||||
{16.5, { 2, 3, 4, 5, 6, 7, 7, 8, 9, 9, 9, 10, 10, 11, 12} },
|
||||
{ 17, { 2, 3, 4, 5, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 12} },
|
||||
{17.5, { 1, 3, 4, 5, 5, 6, 6, 7, 8, 8, 8, 9, 9, 10, 12} },
|
||||
{ 18, { 1, 3, 4, 5, 5, 6, 6, 7, 8, 8, 8, 9, 9, 10, 11} },
|
||||
{18.5, { 1, 3, 4, 5, 5, 6, 6, 7, 8, 8, 8, 9, 9, 10, 11} },
|
||||
{ 19, { 1, 2, 3, 4, 5, 5, 5, 6, 7, 7, 7, 8, 8, 9, 10} },
|
||||
{19.5, { 1, 2, 3, 4, 5, 5, 5, 6, 7, 7, 7, 8, 8, 9, 10} },
|
||||
{ 20, { 1, 2, 3, 3, 4, 5, 5, 6, 6, 6, 6, 7, 7, 8, 10} },
|
||||
{20.5, { 1, 2, 3, 3, 4, 5, 5, 5, 5, 6, 6, 7, 7, 8, 10} },
|
||||
{ 21, { 1, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 7, 7, 8, 10} },
|
||||
{21.5, { 1, 2, 3, 3, 3, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9} },
|
||||
{ 22, { 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 9} },
|
||||
{22.5, { 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8} },
|
||||
{ 23, { 1, 1, 2, 3, 3, 3, 4, 4, 4, 4, 6, 6, 6, 6, 8} },
|
||||
{23.5, { 1, 1, 1, 3, 3, 3, 4, 4, 4, 4, 6, 6, 6, 6, 8} },
|
||||
{ 24, { 1, 1, 1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 6, 8} },
|
||||
{24.5, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 8} },
|
||||
{ 25, { 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 5, 5, 7} },
|
||||
{25.5, { 0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 7} },
|
||||
{ 26, { 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, 6} },
|
||||
{26.5, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 6} },
|
||||
{ 27, { 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 6} },
|
||||
{27.5, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 6} },
|
||||
{ 28, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 5} },
|
||||
{28.5, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 5} },
|
||||
{ 29, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4} },
|
||||
{29.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4} },
|
||||
{ 30, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 4} }
|
||||
};
|
||||
|
||||
|
||||
const qp_table qp_table_422_8bpc_max = {
|
||||
{ 6, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} },
|
||||
{ 6.5, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} },
|
||||
{ 7, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 12} },
|
||||
{ 7.5, { 3, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12} },
|
||||
{ 8, { 2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10, 11} },
|
||||
{ 8.5, { 2, 3, 4, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11} },
|
||||
{ 9, { 1, 2, 3, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10} },
|
||||
{ 9.5, { 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 10} },
|
||||
{ 10, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9} },
|
||||
{10.5, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9} },
|
||||
{ 11, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8} },
|
||||
{11.5, { 0, 1, 1, 2, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8} },
|
||||
{ 12, { 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7} },
|
||||
{12.5, { 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7} },
|
||||
{ 13, { 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6} },
|
||||
{13.5, { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 6} },
|
||||
{ 14, { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5} },
|
||||
{14.5, { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 5} },
|
||||
{ 15, { 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 5} },
|
||||
{15.5, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 4} },
|
||||
{ 16, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 4} }
|
||||
};
|
||||
|
||||
#endif
|
258
drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c
Normal file
258
drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c
Normal file
@ -0,0 +1,258 @@
|
||||
#if defined(CONFIG_DRM_AMD_DC_DSC_SUPPORT)
|
||||
|
||||
/*
|
||||
* Copyright 2017 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 "os_types.h"
|
||||
#include "rc_calc.h"
|
||||
#include "qp_tables.h"
|
||||
|
||||
#define table_hash(mode, bpc, max_min) ((mode << 16) | (bpc << 8) | max_min)
|
||||
|
||||
#define MODE_SELECT(val444, val422, val420) \
|
||||
(cm == CM_444 || cm == CM_RGB) ? (val444) : (cm == CM_422 ? (val422) : (val420))
|
||||
|
||||
|
||||
#define TABLE_CASE(mode, bpc, max) case (table_hash(mode, BPC_##bpc, max)): \
|
||||
table = qp_table_##mode##_##bpc##bpc_##max; \
|
||||
table_size = sizeof(qp_table_##mode##_##bpc##bpc_##max)/sizeof(*qp_table_##mode##_##bpc##bpc_##max); \
|
||||
break
|
||||
|
||||
|
||||
void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc, enum max_min max_min, float bpp)
|
||||
{
|
||||
int mode = MODE_SELECT(444, 422, 420);
|
||||
int sel = table_hash(mode, bpc, max_min);
|
||||
int table_size = 0;
|
||||
int index;
|
||||
const struct qp_entry *table = 0L;
|
||||
|
||||
// alias enum
|
||||
enum { min = MM_MIN, max = MM_MAX };
|
||||
switch (sel) {
|
||||
TABLE_CASE(444, 8, max);
|
||||
TABLE_CASE(444, 8, min);
|
||||
TABLE_CASE(444, 10, max);
|
||||
TABLE_CASE(444, 10, min);
|
||||
TABLE_CASE(444, 12, max);
|
||||
TABLE_CASE(444, 12, min);
|
||||
TABLE_CASE(422, 8, max);
|
||||
TABLE_CASE(422, 8, min);
|
||||
TABLE_CASE(422, 10, max);
|
||||
TABLE_CASE(422, 10, min);
|
||||
TABLE_CASE(422, 12, max);
|
||||
TABLE_CASE(422, 12, min);
|
||||
TABLE_CASE(420, 8, max);
|
||||
TABLE_CASE(420, 8, min);
|
||||
TABLE_CASE(420, 10, max);
|
||||
TABLE_CASE(420, 10, min);
|
||||
TABLE_CASE(420, 12, max);
|
||||
TABLE_CASE(420, 12, min);
|
||||
}
|
||||
|
||||
if (table == 0)
|
||||
return;
|
||||
|
||||
index = (bpp - table[0].bpp) * 2;
|
||||
|
||||
/* requested size is bigger than the table */
|
||||
if (index >= table_size) {
|
||||
dm_error("ERROR: Requested rc_calc to find a bpp entry that exceeds the table size\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(qps, table[index].qps, sizeof(qp_set));
|
||||
}
|
||||
|
||||
double dsc_roundf(double num)
|
||||
{
|
||||
if (num < 0.0)
|
||||
num = num - 0.5;
|
||||
else
|
||||
num = num + 0.5;
|
||||
|
||||
return (int)(num);
|
||||
}
|
||||
|
||||
double dsc_ceil(double num)
|
||||
{
|
||||
double retval = (int)num;
|
||||
|
||||
if (retval != num && num > 0)
|
||||
retval = num + 1;
|
||||
|
||||
return (int)retval;
|
||||
}
|
||||
|
||||
void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp)
|
||||
{
|
||||
int *p = ofs;
|
||||
|
||||
if (mode == CM_444 || mode == CM_RGB) {
|
||||
*p++ = (bpp <= 6) ? (0) : ((((bpp >= 8) && (bpp <= 12))) ? (2) : ((bpp >= 15) ? (10) : ((((bpp > 6) && (bpp < 8))) ? (0 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (2 + dsc_roundf((bpp - 12) * (8 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-2) : ((((bpp >= 8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (8) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (8 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-2) : ((((bpp >= 8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (6) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-4) : ((((bpp >= 8) && (bpp <= 12))) ? (-2) : ((bpp >= 15) ? (4) : ((((bpp > 6) && (bpp < 8))) ? (-4 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (-2 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-6) : ((((bpp >= 8) && (bpp <= 12))) ? (-4) : ((bpp >= 15) ? (2) : ((((bpp > 6) && (bpp < 8))) ? (-6 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (-4 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
|
||||
*p++ = (bpp <= 12) ? (-6) : ((bpp >= 15) ? (0) : (-6 + dsc_roundf((bpp - 12) * (6 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-2) : (-8 + dsc_roundf((bpp - 12) * (6 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-4) : (-8 + dsc_roundf((bpp - 12) * (4 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-6) : (-8 + dsc_roundf((bpp - 12) * (2 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-10) : ((bpp >= 15) ? (-8) : (-10 + dsc_roundf((bpp - 12) * (2 / 3.0))));
|
||||
*p++ = -10;
|
||||
*p++ = (bpp <= 6) ? (-12) : ((bpp >= 8) ? (-10) : (-12 + dsc_roundf((bpp - 6) * (2 / 2.0))));
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
} else if (mode == CM_422) {
|
||||
*p++ = (bpp <= 8) ? (2) : ((bpp >= 10) ? (10) : (2 + dsc_roundf((bpp - 8) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (0) : ((bpp >= 10) ? (8) : (0 + dsc_roundf((bpp - 8) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (0) : ((bpp >= 10) ? (6) : (0 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-2) : ((bpp >= 10) ? (4) : (-2 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-4) : ((bpp >= 10) ? (2) : (-4 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-6) : ((bpp >= 10) ? (0) : (-6 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-2) : (-8 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-4) : (-8 + dsc_roundf((bpp - 8) * (4 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-6) : (-8 + dsc_roundf((bpp - 8) * (2 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-10) : ((bpp >= 10) ? (-8) : (-10 + dsc_roundf((bpp - 8) * (2 / 2.0))));
|
||||
*p++ = -10;
|
||||
*p++ = (bpp <= 6) ? (-12) : ((bpp >= 7) ? (-10) : (-12 + dsc_roundf((bpp - 6) * (2.0 / 1))));
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
} else {
|
||||
*p++ = (bpp <= 6) ? (2) : ((bpp >= 8) ? (10) : (2 + dsc_roundf((bpp - 6) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (0) : ((bpp >= 8) ? (8) : (0 + dsc_roundf((bpp - 6) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (0) : ((bpp >= 8) ? (6) : (0 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-2) : ((bpp >= 8) ? (4) : (-2 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-4) : ((bpp >= 8) ? (2) : (-4 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-6) : ((bpp >= 8) ? (0) : (-6 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-2) : (-8 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-4) : (-8 + dsc_roundf((bpp - 6) * (4 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-6) : (-8 + dsc_roundf((bpp - 6) * (2 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-10) : ((bpp >= 8) ? (-8) : (-10 + dsc_roundf((bpp - 6) * (2 / 2.0))));
|
||||
*p++ = -10;
|
||||
*p++ = (bpp <= 4) ? (-12) : ((bpp >= 5) ? (-10) : (-12 + dsc_roundf((bpp - 4) * (2 / 1.0))));
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
}
|
||||
}
|
||||
|
||||
int median3(int a, int b, int c)
|
||||
{
|
||||
if (a > b)
|
||||
swap(a, b);
|
||||
if (b > c)
|
||||
swap(b, c);
|
||||
if (a > b)
|
||||
swap(b, c);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
void calc_rc_params(struct rc_params *rc, enum colour_mode cm, enum bits_per_comp bpc, float bpp, int slice_width, int slice_height, int minor_version)
|
||||
{
|
||||
float bpp_group;
|
||||
float initial_xmit_delay_factor;
|
||||
int source_bpp;
|
||||
int padding_pixels;
|
||||
int i;
|
||||
|
||||
rc->rc_quant_incr_limit0 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
rc->rc_quant_incr_limit1 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
|
||||
bpp_group = MODE_SELECT(bpp, bpp * 2.0, bpp * 2.0);
|
||||
|
||||
switch (cm) {
|
||||
case CM_420:
|
||||
rc->initial_fullness_offset = (bpp >= 6) ? (2048) : ((bpp <= 4) ? (6144) : ((((bpp > 4) && (bpp <= 5))) ? (6144 - dsc_roundf((bpp - 4) * (512))) : (5632 - dsc_roundf((bpp - 5) * (3584)))));
|
||||
rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)((3 * bpc * 3) - (3 * bpp_group)));
|
||||
rc->second_line_bpg_offset = median3(0, 12, (int)((3 * bpc * 3) - (3 * bpp_group)));
|
||||
break;
|
||||
case CM_422:
|
||||
rc->initial_fullness_offset = (bpp >= 8) ? (2048) : ((bpp <= 7) ? (5632) : (5632 - dsc_roundf((bpp - 7) * (3584))));
|
||||
rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)((3 * bpc * 4) - (3 * bpp_group)));
|
||||
rc->second_line_bpg_offset = 0;
|
||||
break;
|
||||
case CM_444:
|
||||
case CM_RGB:
|
||||
rc->initial_fullness_offset = (bpp >= 12) ? (2048) : ((bpp <= 8) ? (6144) : ((((bpp > 8) && (bpp <= 10))) ? (6144 - dsc_roundf((bpp - 8) * (512 / 2))) : (5632 - dsc_roundf((bpp - 10) * (3584 / 2)))));
|
||||
rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)(((3 * bpc + (cm == CM_444 ? 0 : 2)) * 3) - (3 * bpp_group)));
|
||||
rc->second_line_bpg_offset = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
initial_xmit_delay_factor = (cm == CM_444 || cm == CM_RGB) ? 1.0 : 2.0;
|
||||
rc->initial_xmit_delay = dsc_roundf(8192.0/2.0/bpp/initial_xmit_delay_factor);
|
||||
|
||||
if (cm == CM_422 || cm == CM_420)
|
||||
slice_width /= 2;
|
||||
|
||||
padding_pixels = ((slice_width % 3) != 0) ? (3 - (slice_width % 3)) * (rc->initial_xmit_delay / slice_width) : 0;
|
||||
if (3 * bpp_group >= (((rc->initial_xmit_delay + 2) / 3) * (3 + (cm == CM_422)))) {
|
||||
if ((rc->initial_xmit_delay + padding_pixels) % 3 == 1)
|
||||
rc->initial_xmit_delay++;
|
||||
}
|
||||
|
||||
source_bpp = MODE_SELECT(bpc * 3, bpc * 2, bpc * 1.5);
|
||||
|
||||
rc->flatness_min_qp = ((bpc == BPC_8) ? (3) : ((bpc == BPC_10) ? (7) : (11))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
rc->flatness_max_qp = ((bpc == BPC_8) ? (12) : ((bpc == BPC_10) ? (16) : (20))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
rc->flatness_det_thresh = 2 << (bpc - 8);
|
||||
|
||||
get_qp_set(rc->qp_min, cm, bpc, MM_MIN, bpp);
|
||||
get_qp_set(rc->qp_max, cm, bpc, MM_MAX, bpp);
|
||||
if (cm == CM_444 && minor_version == 1) {
|
||||
for (i = 0; i < QP_SET_SIZE; ++i) {
|
||||
rc->qp_min[i] = rc->qp_min[i] > 0 ? rc->qp_min[i] - 1 : 0;
|
||||
rc->qp_max[i] = rc->qp_max[i] > 0 ? rc->qp_max[i] - 1 : 0;
|
||||
}
|
||||
}
|
||||
get_ofs_set(rc->ofs, cm, bpp);
|
||||
|
||||
/* fixed parameters */
|
||||
rc->rc_model_size = 8192;
|
||||
rc->rc_edge_factor = 6;
|
||||
rc->rc_tgt_offset_hi = 3;
|
||||
rc->rc_tgt_offset_lo = 3;
|
||||
|
||||
rc->rc_buf_thresh[0] = 896;
|
||||
rc->rc_buf_thresh[1] = 1792;
|
||||
rc->rc_buf_thresh[2] = 2688;
|
||||
rc->rc_buf_thresh[3] = 3584;
|
||||
rc->rc_buf_thresh[4] = 4480;
|
||||
rc->rc_buf_thresh[5] = 5376;
|
||||
rc->rc_buf_thresh[6] = 6272;
|
||||
rc->rc_buf_thresh[7] = 6720;
|
||||
rc->rc_buf_thresh[8] = 7168;
|
||||
rc->rc_buf_thresh[9] = 7616;
|
||||
rc->rc_buf_thresh[10] = 7744;
|
||||
rc->rc_buf_thresh[11] = 7872;
|
||||
rc->rc_buf_thresh[12] = 8000;
|
||||
rc->rc_buf_thresh[13] = 8064;
|
||||
}
|
||||
|
||||
#endif
|
85
drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h
Normal file
85
drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h
Normal file
@ -0,0 +1,85 @@
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
|
||||
|
||||
/*
|
||||
* Copyright 2017 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 __RC_CALC_H__
|
||||
#define __RC_CALC_H__
|
||||
|
||||
|
||||
#define QP_SET_SIZE 15
|
||||
|
||||
typedef int qp_set[QP_SET_SIZE];
|
||||
|
||||
struct rc_params {
|
||||
int rc_quant_incr_limit0;
|
||||
int rc_quant_incr_limit1;
|
||||
int initial_fullness_offset;
|
||||
int initial_xmit_delay;
|
||||
int first_line_bpg_offset;
|
||||
int second_line_bpg_offset;
|
||||
int flatness_min_qp;
|
||||
int flatness_max_qp;
|
||||
int flatness_det_thresh;
|
||||
qp_set qp_min;
|
||||
qp_set qp_max;
|
||||
qp_set ofs;
|
||||
int rc_model_size;
|
||||
int rc_edge_factor;
|
||||
int rc_tgt_offset_hi;
|
||||
int rc_tgt_offset_lo;
|
||||
int rc_buf_thresh[QP_SET_SIZE - 1];
|
||||
};
|
||||
|
||||
enum colour_mode {
|
||||
CM_RGB, /* 444 RGB */
|
||||
CM_444, /* 444 YUV or simple 422 */
|
||||
CM_422, /* native 422 */
|
||||
CM_420 /* native 420 */
|
||||
};
|
||||
|
||||
enum bits_per_comp {
|
||||
BPC_8 = 8,
|
||||
BPC_10 = 10,
|
||||
BPC_12 = 12
|
||||
};
|
||||
|
||||
enum max_min {
|
||||
MM_MIN = 0,
|
||||
MM_MAX = 1
|
||||
};
|
||||
|
||||
struct qp_entry {
|
||||
float bpp;
|
||||
const qp_set qps;
|
||||
};
|
||||
|
||||
typedef struct qp_entry qp_table[];
|
||||
|
||||
void calc_rc_params(struct rc_params *rc, enum colour_mode cm, enum bits_per_comp bpc, float bpp, int slice_width, int slice_height, int minor_version);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
147
drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c
Normal file
147
drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c
Normal file
@ -0,0 +1,147 @@
|
||||
#if defined(CONFIG_DRM_AMD_DC_DSC_SUPPORT)
|
||||
/*
|
||||
* Copyright 2012-17 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 "os_types.h"
|
||||
#include <drm/drm_dsc.h>
|
||||
#include "dscc_types.h"
|
||||
#include "rc_calc.h"
|
||||
|
||||
double dsc_ceil(double num);
|
||||
|
||||
static void copy_pps_fields(struct drm_dsc_config *to, const struct drm_dsc_config *from)
|
||||
{
|
||||
to->line_buf_depth = from->line_buf_depth;
|
||||
to->bits_per_component = from->bits_per_component;
|
||||
to->convert_rgb = from->convert_rgb;
|
||||
to->slice_width = from->slice_width;
|
||||
to->slice_height = from->slice_height;
|
||||
to->simple_422 = from->simple_422;
|
||||
to->native_422 = from->native_422;
|
||||
to->native_420 = from->native_420;
|
||||
to->pic_width = from->pic_width;
|
||||
to->pic_height = from->pic_height;
|
||||
to->rc_tgt_offset_high = from->rc_tgt_offset_high;
|
||||
to->rc_tgt_offset_low = from->rc_tgt_offset_low;
|
||||
to->bits_per_pixel = from->bits_per_pixel;
|
||||
to->rc_edge_factor = from->rc_edge_factor;
|
||||
to->rc_quant_incr_limit1 = from->rc_quant_incr_limit1;
|
||||
to->rc_quant_incr_limit0 = from->rc_quant_incr_limit0;
|
||||
to->initial_xmit_delay = from->initial_xmit_delay;
|
||||
to->initial_dec_delay = from->initial_dec_delay;
|
||||
to->block_pred_enable = from->block_pred_enable;
|
||||
to->first_line_bpg_offset = from->first_line_bpg_offset;
|
||||
to->second_line_bpg_offset = from->second_line_bpg_offset;
|
||||
to->initial_offset = from->initial_offset;
|
||||
memcpy(&to->rc_buf_thresh, &from->rc_buf_thresh, sizeof(from->rc_buf_thresh));
|
||||
memcpy(&to->rc_range_params, &from->rc_range_params, sizeof(from->rc_range_params));
|
||||
to->rc_model_size = from->rc_model_size;
|
||||
to->flatness_min_qp = from->flatness_min_qp;
|
||||
to->flatness_max_qp = from->flatness_max_qp;
|
||||
to->initial_scale_value = from->initial_scale_value;
|
||||
to->scale_decrement_interval = from->scale_decrement_interval;
|
||||
to->scale_increment_interval = from->scale_increment_interval;
|
||||
to->nfl_bpg_offset = from->nfl_bpg_offset;
|
||||
to->nsl_bpg_offset = from->nsl_bpg_offset;
|
||||
to->slice_bpg_offset = from->slice_bpg_offset;
|
||||
to->final_offset = from->final_offset;
|
||||
to->vbr_enable = from->vbr_enable;
|
||||
to->slice_chunk_size = from->slice_chunk_size;
|
||||
to->second_line_offset_adj = from->second_line_offset_adj;
|
||||
to->dsc_version_minor = from->dsc_version_minor;
|
||||
}
|
||||
|
||||
static void copy_rc_to_cfg(struct drm_dsc_config *dsc_cfg, const struct rc_params *rc)
|
||||
{
|
||||
int i;
|
||||
|
||||
dsc_cfg->rc_quant_incr_limit0 = rc->rc_quant_incr_limit0;
|
||||
dsc_cfg->rc_quant_incr_limit1 = rc->rc_quant_incr_limit1;
|
||||
dsc_cfg->initial_offset = rc->initial_fullness_offset;
|
||||
dsc_cfg->initial_xmit_delay = rc->initial_xmit_delay;
|
||||
dsc_cfg->first_line_bpg_offset = rc->first_line_bpg_offset;
|
||||
dsc_cfg->second_line_bpg_offset = rc->second_line_bpg_offset;
|
||||
dsc_cfg->flatness_min_qp = rc->flatness_min_qp;
|
||||
dsc_cfg->flatness_max_qp = rc->flatness_max_qp;
|
||||
for (i = 0; i < QP_SET_SIZE; ++i) {
|
||||
dsc_cfg->rc_range_params[i].range_min_qp = rc->qp_min[i];
|
||||
dsc_cfg->rc_range_params[i].range_max_qp = rc->qp_max[i];
|
||||
/* Truncate 8-bit signed value to 6-bit signed value */
|
||||
dsc_cfg->rc_range_params[i].range_bpg_offset = 0x3f & rc->ofs[i];
|
||||
}
|
||||
dsc_cfg->rc_model_size = rc->rc_model_size;
|
||||
dsc_cfg->rc_edge_factor = rc->rc_edge_factor;
|
||||
dsc_cfg->rc_tgt_offset_high = rc->rc_tgt_offset_hi;
|
||||
dsc_cfg->rc_tgt_offset_low = rc->rc_tgt_offset_lo;
|
||||
|
||||
for (i = 0; i < QP_SET_SIZE - 1; ++i)
|
||||
dsc_cfg->rc_buf_thresh[i] = rc->rc_buf_thresh[i];
|
||||
}
|
||||
|
||||
int dscc_compute_dsc_parameters(const struct drm_dsc_config *pps, struct dsc_parameters *dsc_params)
|
||||
{
|
||||
enum colour_mode mode = pps->convert_rgb ? CM_RGB :
|
||||
(pps->simple_422 ? CM_444 :
|
||||
(pps->native_422 ? CM_422 :
|
||||
pps->native_420 ? CM_420 : CM_444));
|
||||
enum bits_per_comp bpc = (pps->bits_per_component == 8) ? BPC_8 :
|
||||
(pps->bits_per_component == 10) ? BPC_10 : BPC_12;
|
||||
float bpp = ((float) pps->bits_per_pixel / 16.0);
|
||||
int slice_width = pps->slice_width;
|
||||
int slice_height = pps->slice_height;
|
||||
int ret;
|
||||
struct rc_params rc;
|
||||
struct drm_dsc_config dsc_cfg;
|
||||
|
||||
double d_bytes_per_pixel = dsc_ceil(bpp * slice_width / 8.0) / slice_width;
|
||||
|
||||
// TODO: Make sure the formula for calculating this is precise (ceiling vs. floor, and at what point they should be applied)
|
||||
if (pps->native_422 || pps->native_420)
|
||||
d_bytes_per_pixel /= 2;
|
||||
|
||||
dsc_params->bytes_per_pixel = (uint32_t)dsc_ceil(d_bytes_per_pixel * 0x10000000);
|
||||
|
||||
/* in native_422 or native_420 modes, the bits_per_pixel is double the target bpp
|
||||
* (the latter is what calc_rc_params expects)
|
||||
*/
|
||||
if (pps->native_422 || pps->native_420)
|
||||
bpp /= 2.0;
|
||||
|
||||
calc_rc_params(&rc, mode, bpc, bpp, slice_width, slice_height, pps->dsc_version_minor);
|
||||
dsc_params->pps = *pps;
|
||||
dsc_params->pps.initial_scale_value = 8 * rc.rc_model_size / (rc.rc_model_size - rc.initial_fullness_offset);
|
||||
|
||||
copy_pps_fields(&dsc_cfg, &dsc_params->pps);
|
||||
copy_rc_to_cfg(&dsc_cfg, &rc);
|
||||
|
||||
dsc_cfg.mux_word_size = dsc_params->pps.bits_per_component <= 10 ? 48 : 64;
|
||||
|
||||
ret = drm_dsc_compute_rc_parameters(&dsc_cfg);
|
||||
|
||||
copy_pps_fields(&dsc_params->pps, &dsc_cfg);
|
||||
dsc_params->rc_buffer_model_size = dsc_cfg.rc_bits;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
@ -43,7 +43,12 @@ enum dc_status {
|
||||
DC_FAIL_BANDWIDTH_VALIDATE = 13, /* BW and Watermark validation */
|
||||
DC_FAIL_SCALING = 14,
|
||||
DC_FAIL_DP_LINK_TRAINING = 15,
|
||||
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
|
||||
DC_FAIL_DSC_VALIDATE = 16,
|
||||
DC_NO_DSC_RESOURCE = 17,
|
||||
#endif
|
||||
DC_FAIL_UNSUPPORTED_1 = 18,
|
||||
|
||||
DC_ERROR_UNEXPECTED = -1
|
||||
};
|
||||
|
||||
|
@ -179,6 +179,9 @@ struct resource_pool {
|
||||
} gsl_groups;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
struct display_stream_compressor *dscs[MAX_PIPES];
|
||||
#endif
|
||||
|
||||
unsigned int pipe_count;
|
||||
unsigned int underlay_pipe_index;
|
||||
@ -219,10 +222,16 @@ struct resource_pool {
|
||||
|
||||
struct dcn_fe_bandwidth {
|
||||
int dppclk_khz;
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
int dscclk_khz;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct stream_resource {
|
||||
struct output_pixel_processor *opp;
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
struct display_stream_compressor *dsc;
|
||||
#endif
|
||||
struct timing_generator *tg;
|
||||
struct stream_encoder *stream_enc;
|
||||
struct audio *audio;
|
||||
|
@ -62,4 +62,10 @@ bool is_dp_active_dongle(const struct dc_link *link);
|
||||
|
||||
void dp_enable_mst_on_sink(struct dc_link *link, bool enable);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
void dp_set_fec_ready(struct dc_link *link, bool ready);
|
||||
void dp_set_fec_enable(struct dc_link *link, bool enable);
|
||||
bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable);
|
||||
#endif
|
||||
|
||||
#endif /* __DC_LINK_DP_H__ */
|
||||
|
101
drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h
Normal file
101
drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2017 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
|
||||
*
|
||||
*/
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
#ifndef __DAL_DSC_H__
|
||||
#define __DAL_DSC_H__
|
||||
|
||||
#include "dc_dsc.h"
|
||||
#include "dc_hw_types.h"
|
||||
#include "dc_dp_types.h"
|
||||
|
||||
/* Input parameters for configuring DSC from the outside of DSC */
|
||||
struct dsc_config {
|
||||
uint32_t pic_width;
|
||||
uint32_t pic_height;
|
||||
enum dc_pixel_encoding pixel_encoding;
|
||||
enum dc_color_depth color_depth; /* Bits per component */
|
||||
struct dc_dsc_config dc_dsc_cfg;
|
||||
};
|
||||
|
||||
|
||||
/* Output parameters for configuring DSC-related part of OPTC */
|
||||
struct dsc_optc_config {
|
||||
uint32_t slice_width; /* Slice width in pixels */
|
||||
uint32_t bytes_per_pixel; /* Bytes per pixel in u3.28 format */
|
||||
bool is_pixel_format_444; /* 'true' if pixel format is 'RGB 444' or 'Simple YCbCr 4:2:2' (4:2:2 upsampled to 4:4:4)' */
|
||||
};
|
||||
|
||||
|
||||
struct dcn_dsc_state {
|
||||
uint32_t dsc_clock_en;
|
||||
uint32_t dsc_slice_width;
|
||||
uint32_t dsc_bytes_per_pixel;
|
||||
};
|
||||
|
||||
|
||||
/* DSC encoder capabilities
|
||||
* They differ from the DPCD DSC caps because they are based on AMD DSC encoder caps.
|
||||
*/
|
||||
union dsc_enc_slice_caps {
|
||||
struct {
|
||||
uint8_t NUM_SLICES_1 : 1;
|
||||
uint8_t NUM_SLICES_2 : 1;
|
||||
uint8_t NUM_SLICES_3 : 1; /* This one is not per DSC spec, but our encoder supports it */
|
||||
uint8_t NUM_SLICES_4 : 1;
|
||||
uint8_t NUM_SLICES_8 : 1;
|
||||
} bits;
|
||||
uint8_t raw;
|
||||
};
|
||||
|
||||
struct dsc_enc_caps {
|
||||
uint8_t dsc_version;
|
||||
union dsc_enc_slice_caps slice_caps;
|
||||
int32_t lb_bit_depth;
|
||||
bool is_block_pred_supported;
|
||||
union dsc_color_formats color_formats;
|
||||
union dsc_color_depth color_depth;
|
||||
int32_t max_total_throughput_mps; /* Maximum total throughput with all the slices combined */
|
||||
int32_t max_slice_width;
|
||||
uint32_t bpp_increment_div; /* bpp increment divisor, e.g. if 16, it's 1/16th of a bit */
|
||||
};
|
||||
|
||||
struct display_stream_compressor {
|
||||
const struct dsc_funcs *funcs;
|
||||
struct dc_context *ctx;
|
||||
int inst;
|
||||
};
|
||||
|
||||
struct dsc_funcs {
|
||||
void (*dsc_get_enc_caps)(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz);
|
||||
void (*dsc_read_state)(struct display_stream_compressor *dsc, struct dcn_dsc_state *s);
|
||||
bool (*dsc_validate_stream)(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg);
|
||||
void (*dsc_set_config)(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
|
||||
struct dsc_optc_config *dsc_optc_cfg, uint8_t *dsc_packed_pps);
|
||||
void (*dsc_enable)(struct display_stream_compressor *dsc, int opp_pipe);
|
||||
void (*dsc_disable)(struct display_stream_compressor *dsc);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
@ -194,6 +194,13 @@ enum opp_regamma {
|
||||
OPP_REGAMMA_USER
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
enum optc_dsc_mode {
|
||||
OPTC_DSC_DISABLED = 0,
|
||||
OPTC_DSC_ENABLED_444 = 1, /* 'RGB 444' or 'Simple YCbCr 4:2:2' (4:2:2 upsampled to 4:4:4) */
|
||||
OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED = 2 /* Native 4:2:2 or 4:2:0 */
|
||||
};
|
||||
#endif
|
||||
|
||||
struct dc_bias_and_scale {
|
||||
uint16_t scale_red;
|
||||
|
@ -118,8 +118,21 @@ struct link_encoder {
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
struct link_enc_state {
|
||||
|
||||
uint32_t dphy_fec_en;
|
||||
uint32_t dphy_fec_ready_shadow;
|
||||
uint32_t dphy_fec_active_status;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
struct link_encoder_funcs {
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
void (*read_state)(
|
||||
struct link_encoder *enc, struct link_enc_state *s);
|
||||
#endif
|
||||
bool (*validate_output_with_stream)(
|
||||
struct link_encoder *enc, const struct dc_stream_state *stream);
|
||||
void (*hw_init)(struct link_encoder *enc);
|
||||
|
@ -109,8 +109,22 @@ struct stream_encoder {
|
||||
enum engine_id id;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
struct enc_state {
|
||||
uint32_t dsc_mode; // DISABLED 0; 1 or 2 indicate enabled state.
|
||||
uint32_t dsc_slice_width;
|
||||
uint32_t sec_gsp7_line_num;
|
||||
uint32_t vbid6_line_reference;
|
||||
uint32_t vbid6_line_num;
|
||||
uint32_t sec_gsp7_enable;
|
||||
uint32_t sec_stream_enable;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct stream_encoder_funcs {
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
void (*enc_read_state)(struct stream_encoder *enc, struct enc_state *s);
|
||||
#endif
|
||||
void (*dp_set_stream_attribute)(
|
||||
struct stream_encoder *enc,
|
||||
struct dc_crtc_timing *crtc_timing,
|
||||
@ -198,6 +212,14 @@ struct stream_encoder_funcs {
|
||||
int tg_inst);
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
void (*dp_set_dsc_config)(
|
||||
struct stream_encoder *enc,
|
||||
enum optc_dsc_mode dsc_mode,
|
||||
uint32_t dsc_bytes_per_pixel,
|
||||
uint32_t dsc_slice_width,
|
||||
uint8_t *dsc_packed_pps);
|
||||
#endif
|
||||
|
||||
void (*set_dynamic_metadata)(struct stream_encoder *enc,
|
||||
bool enable,
|
||||
|
@ -258,6 +258,12 @@ struct timing_generator_funcs {
|
||||
void (*set_vtg_params)(struct timing_generator *optc,
|
||||
const struct dc_crtc_timing *dc_crtc_timing);
|
||||
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
void (*set_dsc_config)(struct timing_generator *optc,
|
||||
enum optc_dsc_mode dsc_mode,
|
||||
uint32_t dsc_bytes_per_pixel,
|
||||
uint32_t dsc_slice_width);
|
||||
#endif
|
||||
void (*set_odm_bypass)(struct timing_generator *tg, const struct dc_crtc_timing *dc_crtc_timing);
|
||||
void (*set_odm_combine)(struct timing_generator *tg, int combine_opp_id, int mpcc_hactive);
|
||||
void (*set_gsl)(struct timing_generator *optc, const struct gsl_params *params);
|
||||
|
@ -46,6 +46,9 @@ struct resource_caps {
|
||||
int num_ddc;
|
||||
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
|
||||
int num_vmid;
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
int num_dsc;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -76,10 +76,20 @@ static void virtual_audio_mute_control(
|
||||
bool mute) {}
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
static void virtual_enc_dp_set_odm_combine(
|
||||
struct stream_encoder *enc,
|
||||
bool odm_combine)
|
||||
{}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const struct stream_encoder_funcs virtual_str_enc_funcs = {
|
||||
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
.dp_set_odm_combine =
|
||||
virtual_enc_dp_set_odm_combine,
|
||||
#endif
|
||||
#endif
|
||||
.dp_set_stream_attribute =
|
||||
virtual_stream_encoder_dp_set_stream_attribute,
|
||||
|
@ -63,6 +63,9 @@
|
||||
#define DC_LOG_IF_TRACE(...) pr_debug("[IF_TRACE]:"__VA_ARGS__)
|
||||
#define DC_LOG_PERF_TRACE(...) DRM_DEBUG_KMS(__VA_ARGS__)
|
||||
#define DC_LOG_RETIMER_REDRIVER(...) DRM_DEBUG_KMS(__VA_ARGS__)
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
#define DC_LOG_DSC(...) DRM_DEBUG_KMS(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
struct dal_logger;
|
||||
|
||||
@ -107,6 +110,9 @@ enum dc_log_type {
|
||||
LOG_PERF_TRACE,
|
||||
LOG_DISPLAYSTATS,
|
||||
LOG_HDMI_RETIMER_REDRIVER,
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
LOG_DSC,
|
||||
#endif
|
||||
LOG_SECTION_TOTAL_COUNT
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user