Commit ab3ee7a5 authored by Zeyu Fan's avatar Zeyu Fan Committed by Alex Deucher

drm/amd/display: OPP refactor and consolidation for DCE.

Signed-off-by: default avatarZeyu Fan <Zeyu.Fan@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent e63d86dc
......@@ -7,7 +7,7 @@
DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \
dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \
dce_clocks.o
dce_clocks.o dce_opp.o
AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE))
......
/*
* Copyright 2012-15 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 "dm_services.h"
#include "basics/conversion.h"
#include "dce_opp.h"
#include "gamma_types.h"
#include "reg_helper.h"
#define REG(reg)\
(opp110->regs->reg)
#undef FN
#define FN(reg_name, field_name) \
opp110->opp_shift->field_name, opp110->opp_mask->field_name
#define CTX \
opp110->base.ctx
enum {
MAX_PWL_ENTRY = 128,
MAX_REGIONS_NUMBER = 16
};
enum {
MAX_LUT_ENTRY = 256,
MAX_NUMBER_OF_ENTRIES = 256
};
enum {
OUTPUT_CSC_MATRIX_SIZE = 12
};
static const struct out_csc_color_matrix global_color_matrix[] = {
{ COLOR_SPACE_SRGB,
{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
{ COLOR_SPACE_SRGB_LIMITED,
{ 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} },
{ COLOR_SPACE_YCBCR601,
{ 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47,
0xF6B9, 0xE00, 0x1000} },
{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA,
0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
/* TODO: correct values below */
{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }
};
enum csc_color_mode {
/* 00 - BITS2:0 Bypass */
CSC_COLOR_MODE_GRAPHICS_BYPASS,
/* 01 - hard coded coefficient TV RGB */
CSC_COLOR_MODE_GRAPHICS_PREDEFINED,
/* 04 - programmable OUTPUT CSC coefficient */
CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC,
};
/*
*****************************************************************************
* Function: regamma_config_regions_and_segments
*
* build regamma curve by using predefined hw points
* uses interface parameters ,like EDID coeff.
*
* @param : parameters interface parameters
* @return void
*
* @note
*
* @see
*
*****************************************************************************
*/
static void regamma_config_regions_and_segments(
struct dce110_opp *opp110,
const struct pwl_params *params)
{
const struct gamma_curve *curve;
uint32_t value = 0;
{
REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0,
REGAMMA_CNTLA_EXP_REGION_START, params->arr_points[0].custom_float_x,
REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, 0);
}
{
REG_SET(REGAMMA_CNTLA_SLOPE_CNTL, 0,
REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, params->arr_points[0].custom_float_slope);
}
{
REG_SET(REGAMMA_CNTLA_END_CNTL1, 0,
REGAMMA_CNTLA_EXP_REGION_END, params->arr_points[1].custom_float_x);
}
{
REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0,
REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[2].custom_float_slope,
REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[1].custom_float_y);
}
curve = params->arr_curve_points;
{
REG_SET_4(REGAMMA_CNTLA_REGION_0_1, 0,
REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
}
curve += 2;
{
REG_SET_4(REGAMMA_CNTLA_REGION_2_3, 0,
REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
}
curve += 2;
{
REG_SET_4(REGAMMA_CNTLA_REGION_4_5, 0,
REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
}
curve += 2;
{
REG_SET_4(REGAMMA_CNTLA_REGION_6_7, 0,
REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
}
curve += 2;
{
REG_SET_4(REGAMMA_CNTLA_REGION_8_9, 0,
REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
}
curve += 2;
{
REG_SET_4(REGAMMA_CNTLA_REGION_10_11, 0,
REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
}
curve += 2;
{
REG_SET_4(REGAMMA_CNTLA_REGION_12_13, 0,
REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
}
curve += 2;
{
REG_SET_4(REGAMMA_CNTLA_REGION_14_15, 0,
REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
}
}
static void program_pwl(
struct dce110_opp *opp110,
const struct pwl_params *params)
{
uint32_t value;
int retval;
{
uint8_t max_tries = 10;
uint8_t counter = 0;
/* Power on LUT memory */
if (REG(DCFE_MEM_PWR_CTRL))
REG_UPDATE(DCFE_MEM_PWR_CTRL,
DCP_REGAMMA_MEM_PWR_DIS, 1);
else
REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL,
REGAMMA_LUT_LIGHT_SLEEP_DIS, 1);
while (counter < max_tries) {
if (REG(DCFE_MEM_PWR_STATUS)) {
value = REG_READ(DCFE_MEM_PWR_STATUS);
REG_GET(DCFE_MEM_PWR_STATUS,
DCP_REGAMMA_MEM_PWR_STATE,
&retval);
if (retval == 0)
break;
++counter;
} else {
value = REG_READ(DCFE_MEM_LIGHT_SLEEP_CNTL);
REG_GET(DCFE_MEM_LIGHT_SLEEP_CNTL,
REGAMMA_LUT_MEM_PWR_STATE,
&retval);
if (retval == 0)
break;
++counter;
}
}
if (counter == max_tries) {
dm_logger_write(opp110->base.ctx->logger, LOG_WARNING,
"%s: regamma lut was not powered on "
"in a timely manner,"
" programming still proceeds\n",
__func__);
}
}
REG_UPDATE(REGAMMA_LUT_WRITE_EN_MASK,
REGAMMA_LUT_WRITE_EN_MASK, 7);
REG_WRITE(REGAMMA_LUT_INDEX, 0);
/* Program REGAMMA_LUT_DATA */
{
uint32_t i = 0;
const struct pwl_result_data *rgb = params->rgb_resulted;
while (i != params->hw_points_num) {
REG_WRITE(REGAMMA_LUT_DATA, rgb->red_reg);
REG_WRITE(REGAMMA_LUT_DATA, rgb->green_reg);
REG_WRITE(REGAMMA_LUT_DATA, rgb->blue_reg);
REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_red_reg);
REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_green_reg);
REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_blue_reg);
++rgb;
++i;
}
}
/* we are done with DCP LUT memory; re-enable low power mode */
if (REG(DCFE_MEM_PWR_CTRL))
REG_UPDATE(DCFE_MEM_PWR_CTRL,
DCP_REGAMMA_MEM_PWR_DIS, 0);
else
REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL,
REGAMMA_LUT_LIGHT_SLEEP_DIS, 0);
}
bool dce110_opp_program_regamma_pwl(
struct output_pixel_processor *opp,
const struct pwl_params *params)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
/* Setup regions */
regamma_config_regions_and_segments(opp110, params);
/* Program PWL */
program_pwl(opp110, params);
return true;
}
void dce110_opp_power_on_regamma_lut(
struct output_pixel_processor *opp,
bool power_on)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
if (REG(DCFE_MEM_PWR_CTRL))
REG_UPDATE_2(DCFE_MEM_PWR_CTRL,
DCP_REGAMMA_MEM_PWR_DIS, power_on,
DCP_LUT_MEM_PWR_DIS, power_on);
else
REG_UPDATE_2(DCFE_MEM_LIGHT_SLEEP_CNTL,
REGAMMA_LUT_LIGHT_SLEEP_DIS, power_on,
DCP_LUT_LIGHT_SLEEP_DIS, power_on);
}
void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp,
enum opp_regamma mode)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
REG_SET(REGAMMA_CONTROL, 0,
GRPH_REGAMMA_MODE, mode);
}
/**
* set_truncation
* 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
* 2) enable truncation
* 3) HW remove 12bit FMT support for DCE11 power saving reason.
*/
static void set_truncation(
struct dce110_opp *opp110,
const struct bit_depth_reduction_params *params)
{
/*Disable truncation*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_TRUNCATE_EN, 0,
FMT_TRUNCATE_DEPTH, 0,
FMT_TRUNCATE_MODE, 0);
/* no 10bpc trunc on DCE11*/
if (params->flags.TRUNCATE_ENABLED == 0 ||
params->flags.TRUNCATE_DEPTH == 2)
return;
/*Set truncation depth and Enable truncation*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_TRUNCATE_EN, 1,
FMT_TRUNCATE_DEPTH, params->flags.TRUNCATE_MODE,
FMT_TRUNCATE_MODE, params->flags.TRUNCATE_DEPTH);
}
/**
* set_spatial_dither
* 1) set spatial dithering mode: pattern of seed
* 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp
* 3) set random seed
* 4) set random mode
* lfsr is reset every frame or not reset
* RGB dithering method
* 0: RGB data are all dithered with x^28+x^3+1
* 1: R data is dithered with x^28+x^3+1
* G data is dithered with x^28+X^9+1
* B data is dithered with x^28+x^13+1
* enable high pass filter or not
* 5) enable spatical dithering
*/
static void set_spatial_dither(
struct dce110_opp *opp110,
const struct bit_depth_reduction_params *params)
{
/*Disable spatial (random) dithering*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_SPATIAL_DITHER_EN, 0,
FMT_SPATIAL_DITHER_DEPTH, 0,
FMT_SPATIAL_DITHER_MODE, 0);
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_HIGHPASS_RANDOM_ENABLE, 0,
FMT_FRAME_RANDOM_ENABLE, 0,
FMT_RGB_RANDOM_ENABLE, 0);
REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_EN, 0);
/* no 10bpc on DCE11*/
if (params->flags.SPATIAL_DITHER_ENABLED == 0 ||
params->flags.SPATIAL_DITHER_DEPTH == 2)
return;
/* only use FRAME_COUNTER_MAX if frameRandom == 1*/
if (opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX &&
opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP) {
if (params->flags.FRAME_RANDOM == 1) {
if (params->flags.SPATIAL_DITHER_DEPTH == 0 ||
params->flags.SPATIAL_DITHER_DEPTH == 1) {
REG_UPDATE_2(FMT_CONTROL,
FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15,
FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2);
} else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
REG_UPDATE_2(FMT_CONTROL,
FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3,
FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1);
} else
return;
} else {
REG_UPDATE_2(FMT_CONTROL,
FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0,
FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0);
}
}
/* Set seed for random values for
* spatial dithering for R,G,B channels
*/
REG_UPDATE(FMT_DITHER_RAND_R_SEED,
FMT_RAND_R_SEED, params->r_seed_value);
REG_UPDATE(FMT_DITHER_RAND_G_SEED,
FMT_RAND_G_SEED, params->g_seed_value);
REG_UPDATE(FMT_DITHER_RAND_B_SEED,
FMT_RAND_B_SEED, params->b_seed_value);
/* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero
* offset for the R/Cr channel, lower 4LSB
* is forced to zeros. Typically set to 0
* RGB and 0x80000 YCbCr.
*/
/* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero
* offset for the G/Y channel, lower 4LSB is
* forced to zeros. Typically set to 0 RGB
* and 0x80000 YCbCr.
*/
/* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero
* offset for the B/Cb channel, lower 4LSB is
* forced to zeros. Typically set to 0 RGB and
* 0x80000 YCbCr.
*/
/* Disable High pass filter
* Reset only at startup
* Set RGB data dithered with x^28+x^3+1
*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM,
FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM,
FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM);
/* Set spatial dithering bit depth
* Set spatial dithering mode
* (default is Seed patterrn AAAA...)
* Enable spatial dithering
*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH,
FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE,
FMT_SPATIAL_DITHER_EN, 1);
}
/**
* SetTemporalDither (Frame Modulation)
* 1) set temporal dither depth
* 2) select pattern: from hard-coded pattern or programmable pattern
* 3) select optimized strips for BGR or RGB LCD sub-pixel
* 4) set s matrix
* 5) set t matrix
* 6) set grey level for 0.25, 0.5, 0.75
* 7) enable temporal dithering
*/
static void set_temporal_dither(
struct dce110_opp *opp110,
const struct bit_depth_reduction_params *params)
{
/*Disable temporal (frame modulation) dithering first*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_EN, 0,
FMT_TEMPORAL_DITHER_RESET, 0,
FMT_TEMPORAL_DITHER_OFFSET, 0);
REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_DEPTH, 0,
FMT_TEMPORAL_LEVEL, 0);
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_25FRC_SEL, 0,
FMT_50FRC_SEL, 0,
FMT_75FRC_SEL, 0);
/* no 10bpc dither on DCE11*/
if (params->flags.FRAME_MODULATION_ENABLED == 0 ||
params->flags.FRAME_MODULATION_DEPTH == 2)
return;
/* Set temporal dithering depth*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_DEPTH, params->flags.FRAME_MODULATION_DEPTH,
FMT_TEMPORAL_DITHER_RESET, 0,
FMT_TEMPORAL_DITHER_OFFSET, 0);
/*Select legacy pattern based on FRC and Temporal level*/
if (REG(FMT_TEMPORAL_DITHER_PATTERN_CONTROL)) {
REG_WRITE(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, 0);
/*Set s matrix*/
REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, 0);
/*Set t matrix*/
REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, 0);
}
/*Select patterns for 0.25, 0.5 and 0.75 grey level*/
REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_LEVEL, params->flags.TEMPORAL_LEVEL);
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_25FRC_SEL, params->flags.FRC25,
FMT_50FRC_SEL, params->flags.FRC50,
FMT_75FRC_SEL, params->flags.FRC75);
/*Enable bit reduction by temporal (frame modulation) dithering*/
REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_EN, 1);
}
/**
* Set Clamping
* 1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
* 1 for 8 bpc
* 2 for 10 bpc
* 3 for 12 bpc
* 7 for programable
* 2) Enable clamp if Limited range requested
*/
void dce110_opp_set_clamping(
struct dce110_opp *opp110,
const struct clamping_and_pixel_encoding_params *params)
{
uint32_t clamp_cntl_value = 0;
REG_SET_2(FMT_CLAMP_CNTL, 0,
FMT_CLAMP_DATA_EN, 0,
FMT_CLAMP_COLOR_FORMAT, 0);
switch (params->clamping_level) {
case CLAMPING_FULL_RANGE:
break;
case CLAMPING_LIMITED_RANGE_8BPC:
REG_SET_2(FMT_CLAMP_CNTL, 0,
FMT_CLAMP_DATA_EN, 1,
FMT_CLAMP_COLOR_FORMAT, 1);
break;
case CLAMPING_LIMITED_RANGE_10BPC:
REG_SET_2(FMT_CLAMP_CNTL, 0,
FMT_CLAMP_DATA_EN, 1,
FMT_CLAMP_COLOR_FORMAT, 2);
break;
case CLAMPING_LIMITED_RANGE_12BPC:
REG_SET_2(FMT_CLAMP_CNTL, 0,
FMT_CLAMP_DATA_EN, 1,
FMT_CLAMP_COLOR_FORMAT, 3);
break;
case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
/*Set clamp control*/
REG_SET_2(FMT_CLAMP_CNTL, 0,
FMT_CLAMP_DATA_EN, 1,
FMT_CLAMP_COLOR_FORMAT, 7);
/*set the defaults*/
REG_SET_2(FMT_CLAMP_COMPONENT_R, 0,
FMT_CLAMP_LOWER_R, 0x10,
FMT_CLAMP_UPPER_R, 0xFEF);
REG_SET_2(FMT_CLAMP_COMPONENT_G, 0,
FMT_CLAMP_LOWER_G, 0x10,
FMT_CLAMP_UPPER_G, 0xFEF);
REG_SET_2(FMT_CLAMP_COMPONENT_B, 0,
FMT_CLAMP_LOWER_B, 0x10,
FMT_CLAMP_UPPER_B, 0xFEF);
break;
default:
break;
}
}
/**
* set_pixel_encoding
*
* Set Pixel Encoding
* 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
* 1: YCbCr 4:2:2
*/
static void set_pixel_encoding(
struct dce110_opp *opp110,
const struct clamping_and_pixel_encoding_params *params)
{
if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS)
REG_UPDATE_3(FMT_CONTROL,
FMT_PIXEL_ENCODING, 0,
FMT_SUBSAMPLING_MODE, 0,
FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
else
REG_UPDATE_2(FMT_CONTROL,
FMT_PIXEL_ENCODING, 0,
FMT_SUBSAMPLING_MODE, 0);
if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
REG_UPDATE_2(FMT_CONTROL,
FMT_PIXEL_ENCODING, 1,
FMT_SUBSAMPLING_ORDER, 0);
}
if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
REG_UPDATE_3(FMT_CONTROL,
FMT_PIXEL_ENCODING, 2,
FMT_SUBSAMPLING_MODE, 2,
FMT_CBCR_BIT_REDUCTION_BYPASS, 1);
}
}
void dce110_opp_program_bit_depth_reduction(
struct output_pixel_processor *opp,
const struct bit_depth_reduction_params *params)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
set_truncation(opp110, params);
set_spatial_dither(opp110, params);
set_temporal_dither(opp110, params);
}
void dce110_opp_program_clamping_and_pixel_encoding(
struct output_pixel_processor *opp,
const struct clamping_and_pixel_encoding_params *params)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
dce110_opp_set_clamping(opp110, params);
set_pixel_encoding(opp110, params);
}
static void program_formatter_420_memory(struct output_pixel_processor *opp)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
uint32_t fmt_mem_cntl_value;
/* Program source select*/
/* Use HW default source select for FMT_MEMORYx_CONTROL */
/* Use that value for FMT_SRC_SELECT as well*/
REG_GET(CONTROL,
FMT420_MEM0_SOURCE_SEL, &fmt_mem_cntl_value);
REG_UPDATE(FMT_CONTROL,
FMT_SRC_SELECT, fmt_mem_cntl_value);
/* Turn on the memory */
REG_UPDATE(CONTROL,
FMT420_MEM0_PWR_FORCE, 0);
}
void dce110_opp_set_dyn_expansion(
struct output_pixel_processor *opp,
enum dc_color_space color_sp,
enum dc_color_depth color_dpth,
enum signal_type signal)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
bool enable_dyn_exp = false;
REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
FMT_DYNAMIC_EXP_EN, 0,
FMT_DYNAMIC_EXP_MODE, 0);
/* From HW programming guide:
FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output
FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/
if (color_sp == COLOR_SPACE_SRGB)
enable_dyn_exp = true;
/*00 - 10-bit -> 12-bit dynamic expansion*/
/*01 - 8-bit -> 12-bit dynamic expansion*/
if (signal == SIGNAL_TYPE_HDMI_TYPE_A) {
switch (color_dpth) {
case COLOR_DEPTH_888:
REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
FMT_DYNAMIC_EXP_EN, enable_dyn_exp ? 1:0,
FMT_DYNAMIC_EXP_MODE, 1);
break;
case COLOR_DEPTH_101010:
REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
FMT_DYNAMIC_EXP_EN, enable_dyn_exp ? 1:0,
FMT_DYNAMIC_EXP_MODE, 0);
break;
case COLOR_DEPTH_121212:
break;
default:
break;
}
}
}
static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
uint8_t counter = 10;
/* clear previous phase lock status*/
REG_UPDATE(FMT_CONTROL,
FMT_420_PIXEL_PHASE_LOCKED_CLEAR, 1);
/* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/
REG_WAIT(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, 1, 10, 10);
}
void dce110_opp_program_fmt(
struct output_pixel_processor *opp,
struct bit_depth_reduction_params *fmt_bit_depth,
struct clamping_and_pixel_encoding_params *clamping)
{
/* dithering is affected by <CrtcSourceSelect>, hence should be
* programmed afterwards */
if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
program_formatter_420_memory(opp);
dce110_opp_program_bit_depth_reduction(
opp,
fmt_bit_depth);
dce110_opp_program_clamping_and_pixel_encoding(
opp,
clamping);
if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
program_formatter_reset_dig_resync_fifo(opp);
return;
}
static void program_color_matrix(
struct dce110_opp *opp110,
const struct out_csc_color_matrix *tbl_entry,
enum grph_color_adjust_option options)
{
{
REG_SET_2(OUTPUT_CSC_C11_C12, 0,
OUTPUT_CSC_C11, tbl_entry->regval[0],
OUTPUT_CSC_C12, tbl_entry->regval[1]);
}
{
REG_SET_2(OUTPUT_CSC_C13_C14, 0,
OUTPUT_CSC_C11, tbl_entry->regval[2],
OUTPUT_CSC_C12, tbl_entry->regval[3]);
}
{
REG_SET_2(OUTPUT_CSC_C21_C22, 0,
OUTPUT_CSC_C11, tbl_entry->regval[4],
OUTPUT_CSC_C12, tbl_entry->regval[5]);
}
{
REG_SET_2(OUTPUT_CSC_C23_C24, 0,
OUTPUT_CSC_C11, tbl_entry->regval[6],
OUTPUT_CSC_C12, tbl_entry->regval[7]);
}
{
REG_SET_2(OUTPUT_CSC_C31_C32, 0,
OUTPUT_CSC_C11, tbl_entry->regval[8],
OUTPUT_CSC_C12, tbl_entry->regval[9]);
}
{
REG_SET_2(OUTPUT_CSC_C33_C34, 0,
OUTPUT_CSC_C11, tbl_entry->regval[10],
OUTPUT_CSC_C12, tbl_entry->regval[11]);
}
}
static bool configure_graphics_mode(
struct dce110_opp *opp110,
enum csc_color_mode config,
enum graphics_csc_adjust_type csc_adjust_type,
enum dc_color_space color_space)
{
struct dc_context *ctx = opp110->base.ctx;
REG_SET(OUTPUT_CSC_CONTROL, 0,
OUTPUT_CSC_GRPH_MODE, 0);
if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) {
if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) {
REG_SET(OUTPUT_CSC_CONTROL, 0,
OUTPUT_CSC_GRPH_MODE, 4);
} else {
switch (color_space) {
case COLOR_SPACE_SRGB:
/* by pass */
REG_SET(OUTPUT_CSC_CONTROL, 0,
OUTPUT_CSC_GRPH_MODE, 0);
break;
case COLOR_SPACE_SRGB_LIMITED:
/* TV RGB */
REG_SET(OUTPUT_CSC_CONTROL, 0,
OUTPUT_CSC_GRPH_MODE, 1);
break;
case COLOR_SPACE_YCBCR601:
case COLOR_SPACE_YPBPR601:
case COLOR_SPACE_YCBCR601_LIMITED:
/* YCbCr601 */
REG_SET(OUTPUT_CSC_CONTROL, 0,
OUTPUT_CSC_GRPH_MODE, 2);
break;
case COLOR_SPACE_YCBCR709:
case COLOR_SPACE_YPBPR709:
case COLOR_SPACE_YCBCR709_LIMITED:
/* YCbCr709 */
REG_SET(OUTPUT_CSC_CONTROL, 0,
OUTPUT_CSC_GRPH_MODE, 3);
break;
default:
return false;
}
}
} else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) {
switch (color_space) {
case COLOR_SPACE_SRGB:
/* by pass */
REG_SET(OUTPUT_CSC_CONTROL, 0,
OUTPUT_CSC_GRPH_MODE, 0);
break;
break;
case COLOR_SPACE_SRGB_LIMITED:
/* TV RGB */
REG_SET(OUTPUT_CSC_CONTROL, 0,
OUTPUT_CSC_GRPH_MODE, 1);
break;
case COLOR_SPACE_YCBCR601:
case COLOR_SPACE_YPBPR601:
case COLOR_SPACE_YCBCR601_LIMITED:
/* YCbCr601 */
REG_SET(OUTPUT_CSC_CONTROL, 0,
OUTPUT_CSC_GRPH_MODE, 2);
break;
case COLOR_SPACE_YCBCR709:
case COLOR_SPACE_YPBPR709:
case COLOR_SPACE_YCBCR709_LIMITED:
/* YCbCr709 */
REG_SET(OUTPUT_CSC_CONTROL, 0,
OUTPUT_CSC_GRPH_MODE, 3);
break;
default:
return false;
}
} else
/* by pass */
REG_SET(OUTPUT_CSC_CONTROL, 0,
OUTPUT_CSC_GRPH_MODE, 0);
return true;
}
void dce110_opp_set_csc_adjustment(
struct output_pixel_processor *opp,
const struct out_csc_color_matrix *tbl_entry)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
enum csc_color_mode config =
CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
program_color_matrix(
opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW);
/* We did everything ,now program DxOUTPUT_CSC_CONTROL */
configure_graphics_mode(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW,
tbl_entry->color_space);
}
void dce110_opp_set_csc_default(
struct output_pixel_processor *opp,
const struct default_adjustment *default_adjust)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
enum csc_color_mode config =
CSC_COLOR_MODE_GRAPHICS_PREDEFINED;
if (default_adjust->force_hw_default == false) {
const struct out_csc_color_matrix *elm;
/* currently parameter not in use */
enum grph_color_adjust_option option =
GRPH_COLOR_MATRIX_HW_DEFAULT;
uint32_t i;
/*
* HW default false we program locally defined matrix
* HW default true we use predefined hw matrix and we
* do not need to program matrix
* OEM wants the HW default via runtime parameter.
*/
option = GRPH_COLOR_MATRIX_SW;
for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) {
elm = &global_color_matrix[i];
if (elm->color_space != default_adjust->out_color_space)
continue;
/* program the matrix with default values from this
* file */
program_color_matrix(opp110, elm, option);
config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
break;
}
}
/* configure the what we programmed :
* 1. Default values from this file
* 2. Use hardware default from ROM_A and we do not need to program
* matrix */
configure_graphics_mode(opp110, config,
default_adjust->csc_adjust_type,
default_adjust->out_color_space);
}
/*****************************************/
/* Constructor, Destructor */
/*****************************************/
static const struct opp_funcs funcs = {
.opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut,
.opp_set_csc_adjustment = dce110_opp_set_csc_adjustment,
.opp_set_csc_default = dce110_opp_set_csc_default,
.opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
.opp_program_regamma_pwl = dce110_opp_program_regamma_pwl,
.opp_set_regamma_mode = dce110_opp_set_regamma_mode,
.opp_destroy = dce110_opp_destroy,
.opp_program_fmt = dce110_opp_program_fmt,
.opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction
};
bool dce110_opp_construct(struct dce110_opp *opp110,
struct dc_context *ctx,
uint32_t inst,
const struct dce_opp_registers *regs,
const struct dce_opp_shift *opp_shift,
const struct dce_opp_mask *opp_mask)
{
opp110->base.funcs = &funcs;
opp110->base.ctx = ctx;
opp110->base.inst = inst;
opp110->regs = regs;
opp110->opp_shift = opp_shift;
opp110->opp_mask = opp_mask;
return true;
}
void dce110_opp_destroy(struct output_pixel_processor **opp)
{
dm_free(FROM_DCE11_OPP(*opp));
*opp = NULL;
}
/* Copyright 2012-15 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 __DC_OPP_DCE_H__
#define __DC_OPP_DCE_H__
#include "dc_types.h"
#include "opp.h"
#include "core_types.h"
#include "gamma_types.h" /* decprecated */
struct gamma_parameters;
#define FROM_DCE11_OPP(opp)\
container_of(opp, struct dce110_opp, base)
enum dce110_opp_reg_type {
DCE110_OPP_REG_DCP = 0,
DCE110_OPP_REG_DCFE,
DCE110_OPP_REG_FMT,
DCE110_OPP_REG_MAX
};
#define OPP_COMMON_REG_LIST_BASE(id) \
SRI(REGAMMA_CNTLA_START_CNTL, DCP, id), \
SRI(REGAMMA_CNTLA_SLOPE_CNTL, DCP, id), \
SRI(REGAMMA_CNTLA_END_CNTL1, DCP, id), \
SRI(REGAMMA_CNTLA_END_CNTL2, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_0_1, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_2_3, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_4_5, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_6_7, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_8_9, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_10_11, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_12_13, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_14_15, DCP, id), \
SRI(REGAMMA_LUT_WRITE_EN_MASK, DCP, id), \
SRI(REGAMMA_LUT_INDEX, DCP, id), \
SRI(REGAMMA_LUT_DATA, DCP, id), \
SRI(REGAMMA_CONTROL, DCP, id), \
SRI(OUTPUT_CSC_C11_C12, DCP, id), \
SRI(OUTPUT_CSC_C13_C14, DCP, id), \
SRI(OUTPUT_CSC_C21_C22, DCP, id), \
SRI(OUTPUT_CSC_C23_C24, DCP, id), \
SRI(OUTPUT_CSC_C31_C32, DCP, id), \
SRI(OUTPUT_CSC_C33_C34, DCP, id), \
SRI(OUTPUT_CSC_CONTROL, DCP, id), \
SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \
SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \
SRI(FMT_CONTROL, FMT, id), \
SRI(FMT_DITHER_RAND_R_SEED, FMT, id), \
SRI(FMT_DITHER_RAND_G_SEED, FMT, id), \
SRI(FMT_DITHER_RAND_B_SEED, FMT, id), \
SRI(FMT_CLAMP_CNTL, FMT, id), \
SRI(FMT_CLAMP_COMPONENT_R, FMT, id), \
SRI(FMT_CLAMP_COMPONENT_G, FMT, id), \
SRI(FMT_CLAMP_COMPONENT_B, FMT, id)
#define OPP_DCE_80_REG_LIST(id) \
OPP_COMMON_REG_LIST_BASE(id), \
SRI(DCFE_MEM_LIGHT_SLEEP_CNTL, CRTC, id), \
SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id)
#define OPP_DCE_100_REG_LIST(id) \
OPP_COMMON_REG_LIST_BASE(id), \
SRI(DCFE_MEM_PWR_CTRL, CRTC, id), \
SRI(DCFE_MEM_PWR_STATUS, CRTC, id), \
SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id)
#define OPP_DCE_110_REG_LIST(id) \
OPP_COMMON_REG_LIST_BASE(id), \
SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \
SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \
SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id)
#define OPP_DCE_112_REG_LIST(id) \
OPP_COMMON_REG_LIST_BASE(id), \
SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \
SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \
SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id), \
SRI(CONTROL, FMT_MEMORY, id)
#define OPP_SF(reg_name, field_name, post_fix)\
.field_name = reg_name ## __ ## field_name ## post_fix
#define OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\
OPP_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\
OPP_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\
OPP_SF(REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\
OPP_SF(REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\
OPP_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\
OPP_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\
OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\
OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\
OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
OPP_SF(REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\
OPP_SF(REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\
OPP_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\
OPP_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\
OPP_SF(OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\
OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\
OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\
OPP_SF(FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh),\
OPP_SF(FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh),\
OPP_SF(FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_RESET, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_OFFSET, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_DEPTH, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_LEVEL, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_25FRC_SEL, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_50FRC_SEL, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_75FRC_SEL, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SRC_SELECT, mask_sh),\
OPP_SF(FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh),\
OPP_SF(FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh),\
OPP_SF(FMT_CLAMP_COMPONENT_R, FMT_CLAMP_LOWER_R, mask_sh),\
OPP_SF(FMT_CLAMP_COMPONENT_R, FMT_CLAMP_UPPER_R, mask_sh),\
OPP_SF(FMT_CLAMP_COMPONENT_G, FMT_CLAMP_LOWER_G, mask_sh),\
OPP_SF(FMT_CLAMP_COMPONENT_G, FMT_CLAMP_UPPER_G, mask_sh),\
OPP_SF(FMT_CLAMP_COMPONENT_B, FMT_CLAMP_LOWER_B, mask_sh),\
OPP_SF(FMT_CLAMP_COMPONENT_B, FMT_CLAMP_UPPER_B, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SUBSAMPLING_MODE, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SUBSAMPLING_ORDER, mask_sh)
#define OPP_COMMON_MASK_SH_LIST_DCE_110(mask_sh)\
OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\
OPP_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\
OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\
OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh)
#define OPP_COMMON_MASK_SH_LIST_DCE_100(mask_sh)\
OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\
OPP_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\
OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\
OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh)
#define OPP_COMMON_MASK_SH_LIST_DCE_112(mask_sh)\
OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\
OPP_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\
OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\
OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\
OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_SOURCE_SEL, mask_sh),\
OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_PWR_FORCE, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED_CLEAR, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_CBCR_BIT_REDUCTION_BYPASS, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh)
#define OPP_COMMON_MASK_SH_LIST_DCE_80(mask_sh)\
OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\
OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_LIGHT_SLEEP_DIS, mask_sh),\
OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, DCP_LUT_LIGHT_SLEEP_DIS, mask_sh),\
OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_MEM_PWR_STATE, mask_sh)
#define OPP_REG_FIELD_LIST(type) \
type DCP_REGAMMA_MEM_PWR_DIS; \
type DCP_LUT_MEM_PWR_DIS; \
type REGAMMA_LUT_LIGHT_SLEEP_DIS; \
type DCP_LUT_LIGHT_SLEEP_DIS; \
type REGAMMA_CNTLA_EXP_REGION_START; \
type REGAMMA_CNTLA_EXP_REGION_START_SEGMENT; \
type REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE; \
type REGAMMA_CNTLA_EXP_REGION_END; \
type REGAMMA_CNTLA_EXP_REGION_END_BASE; \
type REGAMMA_CNTLA_EXP_REGION_END_SLOPE; \
type REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET; \
type REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS; \
type REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET; \
type REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS; \
type DCP_REGAMMA_MEM_PWR_STATE; \
type REGAMMA_LUT_MEM_PWR_STATE; \
type REGAMMA_LUT_WRITE_EN_MASK; \
type GRPH_REGAMMA_MODE; \
type OUTPUT_CSC_C11; \
type OUTPUT_CSC_C12; \
type OUTPUT_CSC_GRPH_MODE; \
type FMT_DYNAMIC_EXP_EN; \
type FMT_DYNAMIC_EXP_MODE; \
type FMT_TRUNCATE_EN; \
type FMT_TRUNCATE_DEPTH; \
type FMT_TRUNCATE_MODE; \
type FMT_SPATIAL_DITHER_EN; \
type FMT_SPATIAL_DITHER_DEPTH; \
type FMT_SPATIAL_DITHER_MODE; \
type FMT_TEMPORAL_DITHER_EN; \
type FMT_TEMPORAL_DITHER_RESET; \
type FMT_TEMPORAL_DITHER_OFFSET; \
type FMT_TEMPORAL_DITHER_DEPTH; \
type FMT_TEMPORAL_LEVEL; \
type FMT_25FRC_SEL; \
type FMT_50FRC_SEL; \
type FMT_75FRC_SEL; \
type FMT_HIGHPASS_RANDOM_ENABLE; \
type FMT_FRAME_RANDOM_ENABLE; \
type FMT_RGB_RANDOM_ENABLE; \
type FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX; \
type FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP; \
type FMT_RAND_R_SEED; \
type FMT_RAND_G_SEED; \
type FMT_RAND_B_SEED; \
type FMT420_MEM0_SOURCE_SEL; \
type FMT420_MEM0_PWR_FORCE; \
type FMT_SRC_SELECT; \
type FMT_420_PIXEL_PHASE_LOCKED_CLEAR; \
type FMT_420_PIXEL_PHASE_LOCKED; \
type FMT_CLAMP_DATA_EN; \
type FMT_CLAMP_COLOR_FORMAT; \
type FMT_CLAMP_LOWER_R; \
type FMT_CLAMP_UPPER_R; \
type FMT_CLAMP_LOWER_G; \
type FMT_CLAMP_UPPER_G; \
type FMT_CLAMP_LOWER_B; \
type FMT_CLAMP_UPPER_B; \
type FMT_PIXEL_ENCODING; \
type FMT_SUBSAMPLING_ORDER; \
type FMT_SUBSAMPLING_MODE; \
type FMT_CBCR_BIT_REDUCTION_BYPASS;\
struct dce_opp_shift {
OPP_REG_FIELD_LIST(uint8_t)
};
struct dce_opp_mask {
OPP_REG_FIELD_LIST(uint32_t)
};
struct dce_opp_registers {
uint32_t DCFE_MEM_PWR_CTRL;
uint32_t DCFE_MEM_LIGHT_SLEEP_CNTL;
uint32_t REGAMMA_CNTLA_START_CNTL;
uint32_t REGAMMA_CNTLA_SLOPE_CNTL;
uint32_t REGAMMA_CNTLA_END_CNTL1;
uint32_t REGAMMA_CNTLA_END_CNTL2;
uint32_t REGAMMA_CNTLA_REGION_0_1;
uint32_t REGAMMA_CNTLA_REGION_2_3;
uint32_t REGAMMA_CNTLA_REGION_4_5;
uint32_t REGAMMA_CNTLA_REGION_6_7;
uint32_t REGAMMA_CNTLA_REGION_8_9;
uint32_t REGAMMA_CNTLA_REGION_10_11;
uint32_t REGAMMA_CNTLA_REGION_12_13;
uint32_t REGAMMA_CNTLA_REGION_14_15;
uint32_t REGAMMA_LUT_WRITE_EN_MASK;
uint32_t REGAMMA_LUT_INDEX;
uint32_t DCFE_MEM_PWR_STATUS;
uint32_t REGAMMA_LUT_DATA;
uint32_t REGAMMA_CONTROL;
uint32_t OUTPUT_CSC_C11_C12;
uint32_t OUTPUT_CSC_C13_C14;
uint32_t OUTPUT_CSC_C21_C22;
uint32_t OUTPUT_CSC_C23_C24;
uint32_t OUTPUT_CSC_C31_C32;
uint32_t OUTPUT_CSC_C33_C34;
uint32_t OUTPUT_CSC_CONTROL;
uint32_t FMT_DYNAMIC_EXP_CNTL;
uint32_t FMT_BIT_DEPTH_CONTROL;
uint32_t FMT_CONTROL;
uint32_t FMT_DITHER_RAND_R_SEED;
uint32_t FMT_DITHER_RAND_G_SEED;
uint32_t FMT_DITHER_RAND_B_SEED;
uint32_t FMT_TEMPORAL_DITHER_PATTERN_CONTROL;
uint32_t FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX;
uint32_t FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX;
uint32_t CONTROL;
uint32_t FMT_CLAMP_CNTL;
uint32_t FMT_CLAMP_COMPONENT_R;
uint32_t FMT_CLAMP_COMPONENT_G;
uint32_t FMT_CLAMP_COMPONENT_B;
};
struct dce110_regamma {
struct gamma_curve arr_curve_points[16];
struct curve_points arr_points[3];
uint32_t hw_points_num;
struct hw_x_point *coordinates_x;
struct pwl_result_data *rgb_resulted;
/* re-gamma curve */
struct pwl_float_data_ex *rgb_regamma;
/* coeff used to map user evenly distributed points
* to our hardware points (predefined) for gamma 256 */
struct pixel_gamma_point *coeff128;
struct pixel_gamma_point *coeff128_oem;
/* coeff used to map user evenly distributed points
* to our hardware points (predefined) for gamma 1025 */
struct pixel_gamma_point *coeff128_dx;
/* evenly distributed points, gamma 256 software points 0-255 */
struct gamma_pixel *axis_x_256;
/* evenly distributed points, gamma 1025 software points 0-1025 */
struct gamma_pixel *axis_x_1025;
/* OEM supplied gamma for regamma LUT */
struct pwl_float_data *rgb_oem;
/* user supplied gamma */
struct pwl_float_data *rgb_user;
uint32_t extra_points;
bool use_half_points;
struct fixed31_32 x_max1;
struct fixed31_32 x_max2;
struct fixed31_32 x_min;
struct fixed31_32 divider1;
struct fixed31_32 divider2;
struct fixed31_32 divider3;
};
/* OPP RELATED */
#define TO_DCE110_OPP(opp)\
container_of(opp, struct dce110_opp, base)
struct dce110_opp {
struct output_pixel_processor base;
const struct dce_opp_registers *regs;
const struct dce_opp_shift *opp_shift;
const struct dce_opp_mask *opp_mask;
struct dce110_regamma regamma;
};
bool dce110_opp_construct(struct dce110_opp *opp110,
struct dc_context *ctx,
uint32_t inst,
const struct dce_opp_registers *regs,
const struct dce_opp_shift *opp_shift,
const struct dce_opp_mask *opp_mask);
void dce110_opp_destroy(struct output_pixel_processor **opp);
/* REGAMMA RELATED */
void dce110_opp_power_on_regamma_lut(
struct output_pixel_processor *opp,
bool power_on);
bool dce110_opp_program_regamma_pwl(
struct output_pixel_processor *opp,
const struct pwl_params *params);
void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp,
enum opp_regamma mode);
void dce110_opp_set_csc_adjustment(
struct output_pixel_processor *opp,
const struct out_csc_color_matrix *tbl_entry);
void dce110_opp_set_csc_default(
struct output_pixel_processor *opp,
const struct default_adjustment *default_adjust);
/* FORMATTER RELATED */
void dce110_opp_program_bit_depth_reduction(
struct output_pixel_processor *opp,
const struct bit_depth_reduction_params *params);
void dce110_opp_program_clamping_and_pixel_encoding(
struct output_pixel_processor *opp,
const struct clamping_and_pixel_encoding_params *params);
void dce110_opp_set_dyn_expansion(
struct output_pixel_processor *opp,
enum dc_color_space color_sp,
enum dc_color_depth color_dpth,
enum signal_type signal);
void dce110_opp_program_fmt(
struct output_pixel_processor *opp,
struct bit_depth_reduction_params *fmt_bit_depth,
struct clamping_and_pixel_encoding_params *clamping);
void dce110_opp_set_clamping(
struct dce110_opp *opp110,
const struct clamping_and_pixel_encoding_params *params);
#endif
......@@ -39,7 +39,7 @@
#include "dce110/dce110_mem_input_v.h"
#include "dce110/dce110_ipp.h"
#include "dce/dce_transform.h"
#include "dce110/dce110_opp.h"
#include "dce/dce_opp.h"
#include "dce/dce_clocks.h"
#include "dce/dce_clock_source.h"
#include "dce/dce_audio.h"
......@@ -302,6 +302,29 @@ static const struct dce_stream_encoder_mask se_mask = {
SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK)
};
#define opp_regs(id)\
[id] = {\
OPP_DCE_100_REG_LIST(id),\
}
static const struct dce_opp_registers opp_regs[] = {
opp_regs(0),
opp_regs(1),
opp_regs(2),
opp_regs(3),
opp_regs(4),
opp_regs(5)
};
static const struct dce_opp_shift opp_shift = {
OPP_COMMON_MASK_SH_LIST_DCE_100(__SHIFT)
};
static const struct dce_opp_mask opp_mask = {
OPP_COMMON_MASK_SH_LIST_DCE_100(_MASK)
};
#define audio_regs(id)\
[id] = {\
AUD_COMMON_REG_LIST(id)\
......@@ -348,35 +371,6 @@ static const struct dce110_clk_src_mask cs_mask = {
#define DCFE_MEM_PWR_CTRL_REG_BASE 0x1b03
static const struct dce110_opp_reg_offsets dce100_opp_reg_offsets[] = {
{
.fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT_CONTROL),
.dcfe_offset = (mmCRTC0_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
.dcp_offset = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
},
{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.dcfe_offset = (mmCRTC1_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
.dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.dcfe_offset = (mmCRTC2_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
.dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{
.fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.dcfe_offset = (mmCRTC3_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
.dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.dcfe_offset = (mmCRTC4_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
.dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.dcfe_offset = (mmCRTC5_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
.dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
}
};
static const struct bios_registers bios_regs = {
.BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6
};
......@@ -615,8 +609,7 @@ struct link_encoder *dce100_link_encoder_create(
struct output_pixel_processor *dce100_opp_create(
struct dc_context *ctx,
uint32_t inst,
const struct dce110_opp_reg_offsets *offset)
uint32_t inst)
{
struct dce110_opp *opp =
dm_alloc(sizeof(struct dce110_opp));
......@@ -625,7 +618,7 @@ struct output_pixel_processor *dce100_opp_create(
return NULL;
if (dce110_opp_construct(opp,
ctx, inst, offset))
ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask))
return &opp->base;
BREAK_TO_DEBUGGER();
......@@ -1052,7 +1045,7 @@ static bool construct(
goto res_create_fail;
}
pool->base.opps[i] = dce100_opp_create(ctx, i, &dce100_opp_reg_offsets[i]);
pool->base.opps[i] = dce100_opp_create(ctx, i);
if (pool->base.opps[i] == NULL) {
BREAK_TO_DEBUGGER();
dm_error(
......
......@@ -3,8 +3,8 @@
# It provides the control and status of HW CRTC block.
DCE110 = dce110_ipp.o dce110_ipp_cursor.o \
dce110_ipp_gamma.o dce110_opp.o dce110_opp_csc.o \
dce110_timing_generator.o dce110_opp_formatter.o dce110_opp_regamma.o \
dce110_ipp_gamma.o \
dce110_timing_generator.o \
dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \
dce110_resource.o \
dce110_opp_regamma_v.o dce110_opp_csc_v.o dce110_timing_generator_v.o \
......
/*
* Copyright 2012-15 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 "dm_services.h"
/* include DCE11 register header files */
#include "dce/dce_11_0_d.h"
#include "dce/dce_11_0_sh_mask.h"
#include "dce110_opp.h"
#include "gamma_types.h"
enum {
MAX_LUT_ENTRY = 256,
MAX_NUMBER_OF_ENTRIES = 256
};
/*****************************************/
/* Constructor, Destructor */
/*****************************************/
static const struct opp_funcs funcs = {
.opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut,
.opp_set_csc_adjustment = dce110_opp_set_csc_adjustment,
.opp_set_csc_default = dce110_opp_set_csc_default,
.opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
.opp_program_regamma_pwl = dce110_opp_program_regamma_pwl,
.opp_set_regamma_mode = dce110_opp_set_regamma_mode,
.opp_destroy = dce110_opp_destroy,
.opp_program_fmt = dce110_opp_program_fmt,
};
bool dce110_opp_construct(struct dce110_opp *opp110,
struct dc_context *ctx,
uint32_t inst,
const struct dce110_opp_reg_offsets *offsets)
{
opp110->base.funcs = &funcs;
opp110->base.ctx = ctx;
opp110->base.inst = inst;
opp110->offsets = *offsets;
return true;
}
void dce110_opp_destroy(struct output_pixel_processor **opp)
{
dm_free(FROM_DCE11_OPP(*opp));
*opp = NULL;
}
/* Copyright 2012-15 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 __DC_OPP_DCE110_H__
#define __DC_OPP_DCE110_H__
#include "dc_types.h"
#include "opp.h"
#include "core_types.h"
#include "gamma_types.h" /* decprecated */
struct gamma_parameters;
#define FROM_DCE11_OPP(opp)\
container_of(opp, struct dce110_opp, base)
enum dce110_opp_reg_type {
DCE110_OPP_REG_DCP = 0,
DCE110_OPP_REG_DCFE,
DCE110_OPP_REG_FMT,
DCE110_OPP_REG_MAX
};
struct dce110_regamma {
struct gamma_curve arr_curve_points[16];
struct curve_points arr_points[3];
uint32_t hw_points_num;
struct hw_x_point *coordinates_x;
struct pwl_result_data *rgb_resulted;
/* re-gamma curve */
struct pwl_float_data_ex *rgb_regamma;
/* coeff used to map user evenly distributed points
* to our hardware points (predefined) for gamma 256 */
struct pixel_gamma_point *coeff128;
struct pixel_gamma_point *coeff128_oem;
/* coeff used to map user evenly distributed points
* to our hardware points (predefined) for gamma 1025 */
struct pixel_gamma_point *coeff128_dx;
/* evenly distributed points, gamma 256 software points 0-255 */
struct gamma_pixel *axis_x_256;
/* evenly distributed points, gamma 1025 software points 0-1025 */
struct gamma_pixel *axis_x_1025;
/* OEM supplied gamma for regamma LUT */
struct pwl_float_data *rgb_oem;
/* user supplied gamma */
struct pwl_float_data *rgb_user;
uint32_t extra_points;
bool use_half_points;
struct fixed31_32 x_max1;
struct fixed31_32 x_max2;
struct fixed31_32 x_min;
struct fixed31_32 divider1;
struct fixed31_32 divider2;
struct fixed31_32 divider3;
};
/* OPP RELATED */
#define TO_DCE110_OPP(opp)\
container_of(opp, struct dce110_opp, base)
struct dce110_opp_reg_offsets {
uint32_t fmt_offset;
uint32_t fmt_mem_offset;
uint32_t dcp_offset;
uint32_t dcfe_offset;
};
struct dce110_opp {
struct output_pixel_processor base;
struct dce110_opp_reg_offsets offsets;
struct dce110_regamma regamma;
};
bool dce110_opp_construct(struct dce110_opp *opp110,
struct dc_context *ctx,
uint32_t inst,
const struct dce110_opp_reg_offsets *offsets);
void dce110_opp_destroy(struct output_pixel_processor **opp);
/* REGAMMA RELATED */
void dce110_opp_power_on_regamma_lut(
struct output_pixel_processor *opp,
bool power_on);
bool dce110_opp_program_regamma_pwl(
struct output_pixel_processor *opp,
const struct pwl_params *params);
void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp,
enum opp_regamma mode);
void dce110_opp_set_csc_adjustment(
struct output_pixel_processor *opp,
const struct out_csc_color_matrix *tbl_entry);
void dce110_opp_set_csc_default(
struct output_pixel_processor *opp,
const struct default_adjustment *default_adjust);
/* FORMATTER RELATED */
void dce110_opp_program_bit_depth_reduction(
struct output_pixel_processor *opp,
const struct bit_depth_reduction_params *params);
void dce110_opp_program_clamping_and_pixel_encoding(
struct output_pixel_processor *opp,
const struct clamping_and_pixel_encoding_params *params);
void dce110_opp_set_dyn_expansion(
struct output_pixel_processor *opp,
enum dc_color_space color_sp,
enum dc_color_depth color_dpth,
enum signal_type signal);
void dce110_opp_program_fmt(
struct output_pixel_processor *opp,
struct bit_depth_reduction_params *fmt_bit_depth,
struct clamping_and_pixel_encoding_params *clamping);
void dce110_opp_set_clamping(
struct dce110_opp *opp110,
const struct clamping_and_pixel_encoding_params *params);
#endif
/*
* Copyright 2012-15 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 "dm_services.h"
#include "dce110_opp.h"
#include "basics/conversion.h"
/* include DCE11 register header files */
#include "dce/dce_11_0_d.h"
#include "dce/dce_11_0_sh_mask.h"
#define DCP_REG(reg)\
(reg + opp110->offsets.dcp_offset)
enum {
OUTPUT_CSC_MATRIX_SIZE = 12
};
static const struct out_csc_color_matrix global_color_matrix[] = {
{ COLOR_SPACE_SRGB,
{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
{ COLOR_SPACE_SRGB_LIMITED,
{ 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} },
{ COLOR_SPACE_YCBCR601,
{ 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47,
0xF6B9, 0xE00, 0x1000} },
{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA,
0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
/* TODO: correct values below */
{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }
};
enum csc_color_mode {
/* 00 - BITS2:0 Bypass */
CSC_COLOR_MODE_GRAPHICS_BYPASS,
/* 01 - hard coded coefficient TV RGB */
CSC_COLOR_MODE_GRAPHICS_PREDEFINED,
/* 04 - programmable OUTPUT CSC coefficient */
CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC,
};
static void program_color_matrix(
struct dce110_opp *opp110,
const struct out_csc_color_matrix *tbl_entry,
enum grph_color_adjust_option options)
{
struct dc_context *ctx = opp110->base.ctx;
{
uint32_t value = 0;
uint32_t addr = DCP_REG(mmOUTPUT_CSC_C11_C12);
/* fixed S2.13 format */
set_reg_field_value(
value,
tbl_entry->regval[0],
OUTPUT_CSC_C11_C12,
OUTPUT_CSC_C11);
set_reg_field_value(
value,
tbl_entry->regval[1],
OUTPUT_CSC_C11_C12,
OUTPUT_CSC_C12);
dm_write_reg(ctx, addr, value);
}
{
uint32_t value = 0;
uint32_t addr = DCP_REG(mmOUTPUT_CSC_C13_C14);
/* fixed S2.13 format */
set_reg_field_value(
value,
tbl_entry->regval[2],
OUTPUT_CSC_C13_C14,
OUTPUT_CSC_C13);
/* fixed S0.13 format */
set_reg_field_value(
value,
tbl_entry->regval[3],
OUTPUT_CSC_C13_C14,
OUTPUT_CSC_C14);
dm_write_reg(ctx, addr, value);
}
{
uint32_t value = 0;
uint32_t addr = DCP_REG(mmOUTPUT_CSC_C21_C22);
/* fixed S2.13 format */
set_reg_field_value(
value,
tbl_entry->regval[4],
OUTPUT_CSC_C21_C22,
OUTPUT_CSC_C21);
/* fixed S2.13 format */
set_reg_field_value(
value,
tbl_entry->regval[5],
OUTPUT_CSC_C21_C22,
OUTPUT_CSC_C22);
dm_write_reg(ctx, addr, value);
}
{
uint32_t value = 0;
uint32_t addr = DCP_REG(mmOUTPUT_CSC_C23_C24);
/* fixed S2.13 format */
set_reg_field_value(
value,
tbl_entry->regval[6],
OUTPUT_CSC_C23_C24,
OUTPUT_CSC_C23);
/* fixed S0.13 format */
set_reg_field_value(
value,
tbl_entry->regval[7],
OUTPUT_CSC_C23_C24,
OUTPUT_CSC_C24);
dm_write_reg(ctx, addr, value);
}
{
uint32_t value = 0;
uint32_t addr = DCP_REG(mmOUTPUT_CSC_C31_C32);
/* fixed S2.13 format */
set_reg_field_value(
value,
tbl_entry->regval[8],
OUTPUT_CSC_C31_C32,
OUTPUT_CSC_C31);
/* fixed S0.13 format */
set_reg_field_value(
value,
tbl_entry->regval[9],
OUTPUT_CSC_C31_C32,
OUTPUT_CSC_C32);
dm_write_reg(ctx, addr, value);
}
{
uint32_t value = 0;
uint32_t addr = DCP_REG(mmOUTPUT_CSC_C33_C34);
/* fixed S2.13 format */
set_reg_field_value(
value,
tbl_entry->regval[10],
OUTPUT_CSC_C33_C34,
OUTPUT_CSC_C33);
/* fixed S0.13 format */
set_reg_field_value(
value,
tbl_entry->regval[11],
OUTPUT_CSC_C33_C34,
OUTPUT_CSC_C34);
dm_write_reg(ctx, addr, value);
}
}
static bool configure_graphics_mode(
struct dce110_opp *opp110,
enum csc_color_mode config,
enum graphics_csc_adjust_type csc_adjust_type,
enum dc_color_space color_space)
{
struct dc_context *ctx = opp110->base.ctx;
uint32_t addr = DCP_REG(mmOUTPUT_CSC_CONTROL);
uint32_t value = dm_read_reg(ctx, addr);
set_reg_field_value(
value,
0,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) {
if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) {
set_reg_field_value(
value,
4,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
} else {
switch (color_space) {
case COLOR_SPACE_SRGB:
/* by pass */
set_reg_field_value(
value,
0,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
case COLOR_SPACE_SRGB_LIMITED:
/* TV RGB */
set_reg_field_value(
value,
1,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
case COLOR_SPACE_YCBCR601:
case COLOR_SPACE_YPBPR601:
case COLOR_SPACE_YCBCR601_LIMITED:
/* YCbCr601 */
set_reg_field_value(
value,
2,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
case COLOR_SPACE_YCBCR709:
case COLOR_SPACE_YPBPR709:
case COLOR_SPACE_YCBCR709_LIMITED:
/* YCbCr709 */
set_reg_field_value(
value,
3,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
default:
return false;
}
}
} else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) {
switch (color_space) {
case COLOR_SPACE_SRGB:
/* by pass */
set_reg_field_value(
value,
0,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
case COLOR_SPACE_SRGB_LIMITED:
/* TV RGB */
set_reg_field_value(
value,
1,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
case COLOR_SPACE_YCBCR601:
case COLOR_SPACE_YPBPR601:
case COLOR_SPACE_YCBCR601_LIMITED:
/* YCbCr601 */
set_reg_field_value(
value,
2,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
case COLOR_SPACE_YCBCR709:
case COLOR_SPACE_YPBPR709:
case COLOR_SPACE_YCBCR709_LIMITED:
/* YCbCr709 */
set_reg_field_value(
value,
3,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
default:
return false;
}
} else
/* by pass */
set_reg_field_value(
value,
0,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
addr = DCP_REG(mmOUTPUT_CSC_CONTROL);
dm_write_reg(ctx, addr, value);
return true;
}
void dce110_opp_set_csc_adjustment(
struct output_pixel_processor *opp,
const struct out_csc_color_matrix *tbl_entry)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
enum csc_color_mode config =
CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
program_color_matrix(
opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW);
/* We did everything ,now program DxOUTPUT_CSC_CONTROL */
configure_graphics_mode(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW,
tbl_entry->color_space);
}
void dce110_opp_set_csc_default(
struct output_pixel_processor *opp,
const struct default_adjustment *default_adjust)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
enum csc_color_mode config =
CSC_COLOR_MODE_GRAPHICS_PREDEFINED;
if (default_adjust->force_hw_default == false) {
const struct out_csc_color_matrix *elm;
/* currently parameter not in use */
enum grph_color_adjust_option option =
GRPH_COLOR_MATRIX_HW_DEFAULT;
uint32_t i;
/*
* HW default false we program locally defined matrix
* HW default true we use predefined hw matrix and we
* do not need to program matrix
* OEM wants the HW default via runtime parameter.
*/
option = GRPH_COLOR_MATRIX_SW;
for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) {
elm = &global_color_matrix[i];
if (elm->color_space != default_adjust->out_color_space)
continue;
/* program the matrix with default values from this
* file */
program_color_matrix(opp110, elm, option);
config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
break;
}
}
/* configure the what we programmed :
* 1. Default values from this file
* 2. Use hardware default from ROM_A and we do not need to program
* matrix */
configure_graphics_mode(opp110, config,
default_adjust->csc_adjust_type,
default_adjust->out_color_space);
}
......@@ -24,7 +24,7 @@
*/
#include "dm_services.h"
#include "dce110_opp.h"
#include "dce/dce_opp.h"
#include "basics/conversion.h"
/* include DCE11 register header files */
......
/*
* Copyright 2012-15 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 "dm_services.h"
#include "dce/dce_11_0_d.h"
#include "dce/dce_11_0_sh_mask.h"
#include "dce110_opp.h"
#define FMT_REG(reg)\
(reg + opp110->offsets.fmt_offset)
/**
* set_truncation
* 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
* 2) enable truncation
* 3) HW remove 12bit FMT support for DCE11 power saving reason.
*/
static void set_truncation(
struct dce110_opp *opp110,
const struct bit_depth_reduction_params *params)
{
uint32_t value = 0;
uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
/*Disable truncation*/
value = dm_read_reg(opp110->base.ctx, addr);
set_reg_field_value(value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN);
set_reg_field_value(value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH);
set_reg_field_value(value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE);
dm_write_reg(opp110->base.ctx, addr, value);
/* no 10bpc trunc on DCE11*/
if (params->flags.TRUNCATE_ENABLED == 0 ||
params->flags.TRUNCATE_DEPTH == 2)
return;
/*Set truncation depth and Enable truncation*/
set_reg_field_value(value, 1,
FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN);
set_reg_field_value(value, params->flags.TRUNCATE_MODE,
FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE);
set_reg_field_value(value, params->flags.TRUNCATE_DEPTH,
FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH);
dm_write_reg(opp110->base.ctx, addr, value);
}
/**
* set_spatial_dither
* 1) set spatial dithering mode: pattern of seed
* 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp
* 3) set random seed
* 4) set random mode
* lfsr is reset every frame or not reset
* RGB dithering method
* 0: RGB data are all dithered with x^28+x^3+1
* 1: R data is dithered with x^28+x^3+1
* G data is dithered with x^28+X^9+1
* B data is dithered with x^28+x^13+1
* enable high pass filter or not
* 5) enable spatical dithering
*/
static void set_spatial_dither(
struct dce110_opp *opp110,
const struct bit_depth_reduction_params *params)
{
uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
uint32_t depth_cntl_value = 0;
uint32_t fmt_cntl_value = 0;
uint32_t dither_r_value = 0;
uint32_t dither_g_value = 0;
uint32_t dither_b_value = 0;
/*Disable spatial (random) dithering*/
depth_cntl_value = dm_read_reg(opp110->base.ctx, addr);
set_reg_field_value(depth_cntl_value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN);
set_reg_field_value(depth_cntl_value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE);
set_reg_field_value(depth_cntl_value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH);
set_reg_field_value(depth_cntl_value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN);
set_reg_field_value(depth_cntl_value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE);
set_reg_field_value(depth_cntl_value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE);
set_reg_field_value(depth_cntl_value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE);
dm_write_reg(opp110->base.ctx, addr, depth_cntl_value);
/* no 10bpc on DCE11*/
if (params->flags.SPATIAL_DITHER_ENABLED == 0 ||
params->flags.SPATIAL_DITHER_DEPTH == 2)
return;
addr = FMT_REG(mmFMT_CONTROL);
fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr);
/* only use FRAME_COUNTER_MAX if frameRandom == 1*/
if (params->flags.FRAME_RANDOM == 1) {
if (params->flags.SPATIAL_DITHER_DEPTH == 0 ||
params->flags.SPATIAL_DITHER_DEPTH == 1) {
set_reg_field_value(fmt_cntl_value, 15,
FMT_CONTROL,
FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX);
set_reg_field_value(fmt_cntl_value, 2,
FMT_CONTROL,
FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP);
} else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
set_reg_field_value(fmt_cntl_value, 3,
FMT_CONTROL,
FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX);
set_reg_field_value(fmt_cntl_value, 1,
FMT_CONTROL,
FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP);
} else
return;
} else {
set_reg_field_value(fmt_cntl_value, 0,
FMT_CONTROL,
FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX);
set_reg_field_value(fmt_cntl_value, 0,
FMT_CONTROL,
FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP);
}
dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value);
/*Set seed for random values for
* spatial dithering for R,G,B channels*/
addr = FMT_REG(mmFMT_DITHER_RAND_R_SEED);
set_reg_field_value(dither_r_value, params->r_seed_value,
FMT_DITHER_RAND_R_SEED,
FMT_RAND_R_SEED);
dm_write_reg(opp110->base.ctx, addr, dither_r_value);
addr = FMT_REG(mmFMT_DITHER_RAND_G_SEED);
set_reg_field_value(dither_g_value,
params->g_seed_value,
FMT_DITHER_RAND_G_SEED,
FMT_RAND_G_SEED);
dm_write_reg(opp110->base.ctx, addr, dither_g_value);
addr = FMT_REG(mmFMT_DITHER_RAND_B_SEED);
set_reg_field_value(dither_b_value, params->b_seed_value,
FMT_DITHER_RAND_B_SEED,
FMT_RAND_B_SEED);
dm_write_reg(opp110->base.ctx, addr, dither_b_value);
/* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero
* offset for the R/Cr channel, lower 4LSB
* is forced to zeros. Typically set to 0
* RGB and 0x80000 YCbCr.
*/
/* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero
* offset for the G/Y channel, lower 4LSB is
* forced to zeros. Typically set to 0 RGB
* and 0x80000 YCbCr.
*/
/* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero
* offset for the B/Cb channel, lower 4LSB is
* forced to zeros. Typically set to 0 RGB and
* 0x80000 YCbCr.
*/
/*Set spatial dithering bit depth*/
set_reg_field_value(depth_cntl_value,
params->flags.SPATIAL_DITHER_DEPTH,
FMT_BIT_DEPTH_CONTROL,
FMT_SPATIAL_DITHER_DEPTH);
/* Set spatial dithering mode
* (default is Seed patterrn AAAA...)
*/
set_reg_field_value(depth_cntl_value,
params->flags.SPATIAL_DITHER_MODE,
FMT_BIT_DEPTH_CONTROL,
FMT_SPATIAL_DITHER_MODE);
/*Reset only at startup*/
set_reg_field_value(depth_cntl_value,
params->flags.FRAME_RANDOM,
FMT_BIT_DEPTH_CONTROL,
FMT_FRAME_RANDOM_ENABLE);
/*Set RGB data dithered with x^28+x^3+1*/
set_reg_field_value(depth_cntl_value,
params->flags.RGB_RANDOM,
FMT_BIT_DEPTH_CONTROL,
FMT_RGB_RANDOM_ENABLE);
/*Disable High pass filter*/
set_reg_field_value(depth_cntl_value,
params->flags.HIGHPASS_RANDOM,
FMT_BIT_DEPTH_CONTROL,
FMT_HIGHPASS_RANDOM_ENABLE);
/*Enable spatial dithering*/
set_reg_field_value(depth_cntl_value,
1,
FMT_BIT_DEPTH_CONTROL,
FMT_SPATIAL_DITHER_EN);
addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
dm_write_reg(opp110->base.ctx, addr, depth_cntl_value);
}
/**
* SetTemporalDither (Frame Modulation)
* 1) set temporal dither depth
* 2) select pattern: from hard-coded pattern or programmable pattern
* 3) select optimized strips for BGR or RGB LCD sub-pixel
* 4) set s matrix
* 5) set t matrix
* 6) set grey level for 0.25, 0.5, 0.75
* 7) enable temporal dithering
*/
static void set_temporal_dither(
struct dce110_opp *opp110,
const struct bit_depth_reduction_params *params)
{
uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
uint32_t value;
/*Disable temporal (frame modulation) dithering first*/
value = dm_read_reg(opp110->base.ctx, addr);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_EN);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_RESET);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_OFFSET);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_DEPTH);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_LEVEL);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_25FRC_SEL);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_50FRC_SEL);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_75FRC_SEL);
dm_write_reg(opp110->base.ctx, addr, value);
/* no 10bpc dither on DCE11*/
if (params->flags.FRAME_MODULATION_ENABLED == 0 ||
params->flags.FRAME_MODULATION_DEPTH == 2)
return;
/* Set temporal dithering depth*/
set_reg_field_value(value,
params->flags.FRAME_MODULATION_DEPTH,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_DEPTH);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_RESET);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_OFFSET);
/*Select legacy pattern based on FRC and Temporal level*/
addr = FMT_REG(mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL);
dm_write_reg(opp110->base.ctx, addr, 0);
/*Set s matrix*/
addr = FMT_REG(
mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX);
dm_write_reg(opp110->base.ctx, addr, 0);
/*Set t matrix*/
addr = FMT_REG(
mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX);
dm_write_reg(opp110->base.ctx, addr, 0);
/*Select patterns for 0.25, 0.5 and 0.75 grey level*/
set_reg_field_value(value,
params->flags.TEMPORAL_LEVEL,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_LEVEL);
set_reg_field_value(value,
params->flags.FRC25,
FMT_BIT_DEPTH_CONTROL,
FMT_25FRC_SEL);
set_reg_field_value(value,
params->flags.FRC50,
FMT_BIT_DEPTH_CONTROL,
FMT_50FRC_SEL);
set_reg_field_value(value,
params->flags.FRC75,
FMT_BIT_DEPTH_CONTROL,
FMT_75FRC_SEL);
/*Enable bit reduction by temporal (frame modulation) dithering*/
set_reg_field_value(value,
1,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_EN);
addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
dm_write_reg(opp110->base.ctx, addr, value);
}
/**
* Set Clamping
* 1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
* 1 for 8 bpc
* 2 for 10 bpc
* 3 for 12 bpc
* 7 for programable
* 2) Enable clamp if Limited range requested
*/
void dce110_opp_set_clamping(
struct dce110_opp *opp110,
const struct clamping_and_pixel_encoding_params *params)
{
uint32_t clamp_cntl_value = 0;
uint32_t red_clamp_value = 0;
uint32_t green_clamp_value = 0;
uint32_t blue_clamp_value = 0;
uint32_t addr = FMT_REG(mmFMT_CLAMP_CNTL);
clamp_cntl_value = dm_read_reg(opp110->base.ctx, addr);
set_reg_field_value(clamp_cntl_value,
0,
FMT_CLAMP_CNTL,
FMT_CLAMP_DATA_EN);
set_reg_field_value(clamp_cntl_value,
0,
FMT_CLAMP_CNTL,
FMT_CLAMP_COLOR_FORMAT);
switch (params->clamping_level) {
case CLAMPING_FULL_RANGE:
break;
case CLAMPING_LIMITED_RANGE_8BPC:
set_reg_field_value(clamp_cntl_value,
1,
FMT_CLAMP_CNTL,
FMT_CLAMP_DATA_EN);
set_reg_field_value(clamp_cntl_value,
1,
FMT_CLAMP_CNTL,
FMT_CLAMP_COLOR_FORMAT);
break;
case CLAMPING_LIMITED_RANGE_10BPC:
set_reg_field_value(clamp_cntl_value,
1,
FMT_CLAMP_CNTL,
FMT_CLAMP_DATA_EN);
set_reg_field_value(clamp_cntl_value,
2,
FMT_CLAMP_CNTL,
FMT_CLAMP_COLOR_FORMAT);
break;
case CLAMPING_LIMITED_RANGE_12BPC:
set_reg_field_value(clamp_cntl_value,
1,
FMT_CLAMP_CNTL,
FMT_CLAMP_DATA_EN);
set_reg_field_value(clamp_cntl_value,
3,
FMT_CLAMP_CNTL,
FMT_CLAMP_COLOR_FORMAT);
break;
case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
set_reg_field_value(clamp_cntl_value,
1,
FMT_CLAMP_CNTL,
FMT_CLAMP_DATA_EN);
set_reg_field_value(clamp_cntl_value,
7,
FMT_CLAMP_CNTL,
FMT_CLAMP_COLOR_FORMAT);
/*set the defaults*/
set_reg_field_value(red_clamp_value,
0x10,
FMT_CLAMP_COMPONENT_R,
FMT_CLAMP_LOWER_R);
set_reg_field_value(red_clamp_value,
0xFEF,
FMT_CLAMP_COMPONENT_R,
FMT_CLAMP_UPPER_R);
addr = FMT_REG(mmFMT_CLAMP_COMPONENT_R);
dm_write_reg(opp110->base.ctx, addr, red_clamp_value);
set_reg_field_value(green_clamp_value,
0x10,
FMT_CLAMP_COMPONENT_G,
FMT_CLAMP_LOWER_G);
set_reg_field_value(green_clamp_value,
0xFEF,
FMT_CLAMP_COMPONENT_G,
FMT_CLAMP_UPPER_G);
addr = FMT_REG(mmFMT_CLAMP_COMPONENT_G);
dm_write_reg(opp110->base.ctx, addr, green_clamp_value);
set_reg_field_value(blue_clamp_value,
0x10,
FMT_CLAMP_COMPONENT_B,
FMT_CLAMP_LOWER_B);
set_reg_field_value(blue_clamp_value,
0xFEF,
FMT_CLAMP_COMPONENT_B,
FMT_CLAMP_UPPER_B);
addr = FMT_REG(mmFMT_CLAMP_COMPONENT_B);
dm_write_reg(opp110->base.ctx, addr, blue_clamp_value);
break;
default:
break;
}
addr = FMT_REG(mmFMT_CLAMP_CNTL);
/*Set clamp control*/
dm_write_reg(opp110->base.ctx, addr, clamp_cntl_value);
}
/**
* set_pixel_encoding
*
* Set Pixel Encoding
* 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
* 1: YCbCr 4:2:2
*/
static void set_pixel_encoding(
struct dce110_opp *opp110,
const struct clamping_and_pixel_encoding_params *params)
{
uint32_t fmt_cntl_value;
uint32_t addr = FMT_REG(mmFMT_CONTROL);
/*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/
fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr);
set_reg_field_value(fmt_cntl_value,
0,
FMT_CONTROL,
FMT_PIXEL_ENCODING);
if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
set_reg_field_value(fmt_cntl_value,
1,
FMT_CONTROL,
FMT_PIXEL_ENCODING);
/*00 - Pixels drop mode ,01 - Pixels average mode*/
set_reg_field_value(fmt_cntl_value,
0,
FMT_CONTROL,
FMT_SUBSAMPLING_MODE);
/*00 - Cb before Cr ,01 - Cr before Cb*/
set_reg_field_value(fmt_cntl_value,
0,
FMT_CONTROL,
FMT_SUBSAMPLING_ORDER);
}
dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value);
}
void dce110_opp_program_bit_depth_reduction(
struct output_pixel_processor *opp,
const struct bit_depth_reduction_params *params)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
set_truncation(opp110, params);
set_spatial_dither(opp110, params);
set_temporal_dither(opp110, params);
}
void dce110_opp_program_clamping_and_pixel_encoding(
struct output_pixel_processor *opp,
const struct clamping_and_pixel_encoding_params *params)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
dce110_opp_set_clamping(opp110, params);
set_pixel_encoding(opp110, params);
}
void dce110_opp_set_dyn_expansion(
struct output_pixel_processor *opp,
enum dc_color_space color_sp,
enum dc_color_depth color_dpth,
enum signal_type signal)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
uint32_t value;
bool enable_dyn_exp = false;
uint32_t addr = FMT_REG(mmFMT_DYNAMIC_EXP_CNTL);
value = dm_read_reg(opp->ctx, addr);
set_reg_field_value(value, 0,
FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN);
set_reg_field_value(value, 0,
FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE);
/* From HW programming guide:
FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output
FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/
if (color_sp == COLOR_SPACE_SRGB)
enable_dyn_exp = true;
/*00 - 10-bit -> 12-bit dynamic expansion*/
/*01 - 8-bit -> 12-bit dynamic expansion*/
if (signal == SIGNAL_TYPE_HDMI_TYPE_A) {
switch (color_dpth) {
case COLOR_DEPTH_888:
set_reg_field_value(value, enable_dyn_exp ? 1:0,
FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN);
set_reg_field_value(value, 1,
FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE);
break;
case COLOR_DEPTH_101010:
set_reg_field_value(value, enable_dyn_exp ? 1:0,
FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN);
set_reg_field_value(value, 0,
FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE);
break;
case COLOR_DEPTH_121212:
break;
default:
break;
}
}
dm_write_reg(opp->ctx, addr, value);
}
void dce110_opp_program_fmt(
struct output_pixel_processor *opp,
struct bit_depth_reduction_params *fmt_bit_depth,
struct clamping_and_pixel_encoding_params *clamping)
{
/* dithering is affected by <CrtcSourceSelect>, hence should be
* programmed afterwards */
dce110_opp_program_bit_depth_reduction(
opp,
fmt_bit_depth);
dce110_opp_program_clamping_and_pixel_encoding(
opp,
clamping);
return;
}
/*
* Copyright 2012-15 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 "dm_services.h"
/* include DCE11 register header files */
#include "dce/dce_11_0_d.h"
#include "dce/dce_11_0_sh_mask.h"
#include "dce110_opp.h"
#include "gamma_types.h"
#define DCP_REG(reg)\
(reg + opp110->offsets.dcp_offset)
#define DCFE_REG(reg)\
(reg + opp110->offsets.dcfe_offset)
enum {
MAX_PWL_ENTRY = 128,
MAX_REGIONS_NUMBER = 16
};
/*
*****************************************************************************
* Function: regamma_config_regions_and_segments
*
* build regamma curve by using predefined hw points
* uses interface parameters ,like EDID coeff.
*
* @param : parameters interface parameters
* @return void
*
* @note
*
* @see
*
*****************************************************************************
*/
static void regamma_config_regions_and_segments(
struct dce110_opp *opp110,
const struct pwl_params *params)
{
const struct gamma_curve *curve;
uint32_t value = 0;
{
set_reg_field_value(
value,
params->arr_points[0].custom_float_x,
REGAMMA_CNTLA_START_CNTL,
REGAMMA_CNTLA_EXP_REGION_START);
set_reg_field_value(
value,
0,
REGAMMA_CNTLA_START_CNTL,
REGAMMA_CNTLA_EXP_REGION_START_SEGMENT);
dm_write_reg(opp110->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_START_CNTL),
value);
}
{
value = 0;
set_reg_field_value(
value,
params->arr_points[0].custom_float_slope,
REGAMMA_CNTLA_SLOPE_CNTL,
REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE);
dm_write_reg(opp110->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_SLOPE_CNTL), value);
}
{
value = 0;
set_reg_field_value(
value,
params->arr_points[1].custom_float_x,
REGAMMA_CNTLA_END_CNTL1,
REGAMMA_CNTLA_EXP_REGION_END);
dm_write_reg(opp110->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_END_CNTL1), value);
}
{
value = 0;
set_reg_field_value(
value,
params->arr_points[2].custom_float_slope,
REGAMMA_CNTLA_END_CNTL2,
REGAMMA_CNTLA_EXP_REGION_END_BASE);
set_reg_field_value(
value,
params->arr_points[1].custom_float_y,
REGAMMA_CNTLA_END_CNTL2,
REGAMMA_CNTLA_EXP_REGION_END_SLOPE);
dm_write_reg(opp110->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value);
}
curve = params->arr_curve_points;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_0_1,
REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_0_1,
REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_0_1,
REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_0_1,
REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS);
dm_write_reg(
opp110->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_0_1),
value);
}
curve += 2;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_2_3,
REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_2_3,
REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_2_3,
REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_2_3,
REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS);
dm_write_reg(opp110->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_2_3),
value);
}
curve += 2;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_4_5,
REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_4_5,
REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_4_5,
REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_4_5,
REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS);
dm_write_reg(opp110->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_4_5),
value);
}
curve += 2;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_6_7,
REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_6_7,
REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_6_7,
REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_6_7,
REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS);
dm_write_reg(opp110->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_6_7),
value);
}
curve += 2;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_8_9,
REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_8_9,
REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_8_9,
REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_8_9,
REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS);
dm_write_reg(opp110->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_8_9),
value);
}
curve += 2;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_10_11,
REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_10_11,
REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_10_11,
REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_10_11,
REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS);
dm_write_reg(opp110->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_10_11),
value);
}
curve += 2;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_12_13,
REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_12_13,
REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_12_13,
REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_12_13,
REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS);
dm_write_reg(opp110->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_12_13),
value);
}
curve += 2;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_14_15,
REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_14_15,
REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_14_15,
REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_14_15,
REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS);
dm_write_reg(opp110->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_14_15),
value);
}
}
static void program_pwl(
struct dce110_opp *opp110,
const struct pwl_params *params)
{
uint32_t value;
{
uint8_t max_tries = 10;
uint8_t counter = 0;
/* Power on LUT memory */
value = dm_read_reg(opp110->base.ctx,
DCFE_REG(mmDCFE_MEM_PWR_CTRL));
set_reg_field_value(
value,
1,
DCFE_MEM_PWR_CTRL,
DCP_REGAMMA_MEM_PWR_DIS);
dm_write_reg(opp110->base.ctx,
DCFE_REG(mmDCFE_MEM_PWR_CTRL), value);
while (counter < max_tries) {
value =
dm_read_reg(
opp110->base.ctx,
DCFE_REG(mmDCFE_MEM_PWR_STATUS));
if (get_reg_field_value(
value,
DCFE_MEM_PWR_STATUS,
DCP_REGAMMA_MEM_PWR_STATE) == 0)
break;
++counter;
}
if (counter == max_tries) {
dm_logger_write(opp110->base.ctx->logger, LOG_WARNING,
"%s: regamma lut was not powered on "
"in a timely manner,"
" programming still proceeds\n",
__func__);
}
}
value = 0;
set_reg_field_value(
value,
7,
REGAMMA_LUT_WRITE_EN_MASK,
REGAMMA_LUT_WRITE_EN_MASK);
dm_write_reg(opp110->base.ctx,
DCP_REG(mmREGAMMA_LUT_WRITE_EN_MASK), value);
dm_write_reg(opp110->base.ctx,
DCP_REG(mmREGAMMA_LUT_INDEX), 0);
/* Program REGAMMA_LUT_DATA */
{
const uint32_t addr = DCP_REG(mmREGAMMA_LUT_DATA);
uint32_t i = 0;
const struct pwl_result_data *rgb = params->rgb_resulted;
while (i != params->hw_points_num) {
dm_write_reg(opp110->base.ctx, addr, rgb->red_reg);
dm_write_reg(opp110->base.ctx, addr, rgb->green_reg);
dm_write_reg(opp110->base.ctx, addr, rgb->blue_reg);
dm_write_reg(opp110->base.ctx, addr,
rgb->delta_red_reg);
dm_write_reg(opp110->base.ctx, addr,
rgb->delta_green_reg);
dm_write_reg(opp110->base.ctx, addr,
rgb->delta_blue_reg);
++rgb;
++i;
}
}
/* we are done with DCP LUT memory; re-enable low power mode */
value = dm_read_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL));
set_reg_field_value(
value,
0,
DCFE_MEM_PWR_CTRL,
DCP_REGAMMA_MEM_PWR_DIS);
dm_write_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value);
}
bool dce110_opp_program_regamma_pwl(
struct output_pixel_processor *opp,
const struct pwl_params *params)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
/* Setup regions */
regamma_config_regions_and_segments(opp110, params);
/* Program PWL */
program_pwl(opp110, params);
return true;
}
void dce110_opp_power_on_regamma_lut(
struct output_pixel_processor *opp,
bool power_on)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
uint32_t value =
dm_read_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL));
set_reg_field_value(
value,
power_on,
DCFE_MEM_PWR_CTRL,
DCP_REGAMMA_MEM_PWR_DIS);
set_reg_field_value(
value,
power_on,
DCFE_MEM_PWR_CTRL,
DCP_LUT_MEM_PWR_DIS);
dm_write_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value);
}
void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp,
enum opp_regamma mode)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
uint32_t value = dm_read_reg(opp110->base.ctx,
DCP_REG(mmREGAMMA_CONTROL));
set_reg_field_value(
value,
mode,
REGAMMA_CONTROL,
GRPH_REGAMMA_MODE);
dm_write_reg(opp110->base.ctx, DCP_REG(mmREGAMMA_CONTROL),
value);
}
......@@ -29,7 +29,7 @@
#include "dce/dce_11_0_d.h"
#include "dce/dce_11_0_sh_mask.h"
#include "dce110_opp.h"
#include "dce/dce_opp.h"
#include "gamma_types.h"
static void power_on_lut(struct output_pixel_processor *opp,
......
......@@ -29,7 +29,7 @@
#include "dce/dce_11_0_d.h"
#include "dce/dce_11_0_sh_mask.h"
#include "dce110_opp.h"
#include "dce/dce_opp.h"
#include "dce110_opp_v.h"
#include "gamma_types.h"
......
......@@ -43,7 +43,7 @@
#include "dce110/dce110_ipp.h"
#include "dce/dce_transform.h"
#include "dce110/dce110_transform_v.h"
#include "dce110/dce110_opp.h"
#include "dce/dce_opp.h"
#include "dce110/dce110_opp_v.h"
#include "dce/dce_clocks.h"
#include "dce/dce_clock_source.h"
......@@ -283,6 +283,28 @@ static const struct dce_stream_encoder_mask se_mask = {
SE_COMMON_MASK_SH_LIST_DCE110(_MASK)
};
#define opp_regs(id)\
[id] = {\
OPP_DCE_110_REG_LIST(id),\
}
static const struct dce_opp_registers opp_regs[] = {
opp_regs(0),
opp_regs(1),
opp_regs(2),
opp_regs(3),
opp_regs(4),
opp_regs(5)
};
static const struct dce_opp_shift opp_shift = {
OPP_COMMON_MASK_SH_LIST_DCE_110(__SHIFT)
};
static const struct dce_opp_mask opp_mask = {
OPP_COMMON_MASK_SH_LIST_DCE_110(_MASK)
};
#define audio_regs(id)\
[id] = {\
AUD_COMMON_REG_LIST(id)\
......@@ -307,34 +329,7 @@ static const struct dce_aduio_mask audio_mask = {
};
/* AG TBD Needs to be reduced back to 3 pipes once dce10 hw sequencer implemented. */
static const struct dce110_opp_reg_offsets dce110_opp_reg_offsets[] = {
{
.fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
.dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
.dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
.dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{
.fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.dcfe_offset = (mmDCFE3_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
.dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.dcfe_offset = (mmDCFE4_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
.dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
.dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
}
};
#define clk_src_regs(id)\
[id] = {\
......@@ -603,8 +598,7 @@ struct link_encoder *dce110_link_encoder_create(
static struct output_pixel_processor *dce110_opp_create(
struct dc_context *ctx,
uint32_t inst,
const struct dce110_opp_reg_offsets *offsets)
uint32_t inst)
{
struct dce110_opp *opp =
dm_alloc(sizeof(struct dce110_opp));
......@@ -613,7 +607,7 @@ static struct output_pixel_processor *dce110_opp_create(
return NULL;
if (dce110_opp_construct(opp,
ctx, inst, offsets))
ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask))
return &opp->base;
BREAK_TO_DEBUGGER();
......@@ -1329,7 +1323,7 @@ static bool construct(
goto res_create_fail;
}
pool->base.opps[i] = dce110_opp_create(ctx, i, &dce110_opp_reg_offsets[i]);
pool->base.opps[i] = dce110_opp_create(ctx, i);
if (pool->base.opps[i] == NULL) {
BREAK_TO_DEBUGGER();
dm_error(
......
......@@ -3,8 +3,7 @@
# It provides the control and status of HW CRTC block.
DCE112 = dce112_compressor.o dce112_hw_sequencer.o \
dce112_resource.o dce112_mem_input.o dce112_opp_formatter.o \
dce112_opp.o
dce112_resource.o dce112_mem_input.o
AMD_DAL_DCE112 = $(addprefix $(AMDDALPATH)/dc/dce112/,$(DCE112))
......
/*
* Copyright 2012-15 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 "dm_services.h"
/* include DCE11 register header files */
#include "dce/dce_11_2_d.h"
#include "dce/dce_11_2_sh_mask.h"
#include "dce112_opp.h"
#include "gamma_types.h"
enum {
MAX_LUT_ENTRY = 256,
MAX_NUMBER_OF_ENTRIES = 256
};
/*****************************************/
/* Constructor, Destructor */
/*****************************************/
static struct opp_funcs funcs = {
.opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut,
.opp_set_csc_adjustment = dce110_opp_set_csc_adjustment,
.opp_set_csc_default = dce110_opp_set_csc_default,
.opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
.opp_program_regamma_pwl = dce110_opp_program_regamma_pwl,
.opp_set_regamma_mode = dce110_opp_set_regamma_mode,
.opp_destroy = dce110_opp_destroy,
.opp_program_fmt = dce112_opp_program_fmt,
.opp_program_bit_depth_reduction =
dce110_opp_program_bit_depth_reduction
};
bool dce112_opp_construct(struct dce110_opp *opp110,
struct dc_context *ctx,
uint32_t inst,
const struct dce110_opp_reg_offsets *offsets)
{
opp110->base.funcs = &funcs;
opp110->base.ctx = ctx;
opp110->base.inst = inst;
opp110->offsets = *offsets;
return true;
}
/* Copyright 2012-15 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 __DC_OPP_DCE112_H__
#define __DC_OPP_DCE112_H__
#include "dc_types.h"
#include "opp.h"
#include "../dce110/dce110_opp.h"
#include "core_types.h"
void dce112_opp_program_clamping_and_pixel_encoding(
struct output_pixel_processor *opp,
const struct clamping_and_pixel_encoding_params *params);
void dce112_opp_program_fmt(
struct output_pixel_processor *opp,
struct bit_depth_reduction_params *fmt_bit_depth,
struct clamping_and_pixel_encoding_params *clamping);
bool dce112_opp_construct(struct dce110_opp *opp110,
struct dc_context *ctx,
uint32_t inst,
const struct dce110_opp_reg_offsets *offsets);
#endif
/*
* Copyright 2012-15 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 "dm_services.h"
#include "dce/dce_11_2_d.h"
#include "dce/dce_11_2_sh_mask.h"
#include "dce112_opp.h"
#define FMT_REG(reg)\
(reg + opp110->offsets.fmt_offset)
#define FMT_MEM_REG(reg)\
(reg + opp110->offsets.fmt_mem_offset)
/**
* Set Clamping
* 1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
* 1 for 8 bpc
* 2 for 10 bpc
* 3 for 12 bpc
* 7 for programable
* 2) Enable clamp if Limited range requested
*/
/**
* set_pixel_encoding
*
* Set Pixel Encoding
* 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
* 1: YCbCr 4:2:2
* 2: YCbCr 4:2:0
*/
static void set_pixel_encoding(
struct dce110_opp *opp110,
const struct clamping_and_pixel_encoding_params *params)
{
uint32_t fmt_cntl_value;
uint32_t addr = FMT_REG(mmFMT_CONTROL);
/*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/
fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr);
set_reg_field_value(fmt_cntl_value,
0,
FMT_CONTROL,
FMT_PIXEL_ENCODING);
/*00 - Pixels drop mode HW default*/
set_reg_field_value(fmt_cntl_value,
0,
FMT_CONTROL,
FMT_SUBSAMPLING_MODE);
/* By default no bypass*/
set_reg_field_value(fmt_cntl_value,
0,
FMT_CONTROL,
FMT_CBCR_BIT_REDUCTION_BYPASS);
if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
set_reg_field_value(fmt_cntl_value,
1,
FMT_CONTROL,
FMT_PIXEL_ENCODING);
/*00 - Cb before Cr ,01 - Cr before Cb*/
set_reg_field_value(fmt_cntl_value,
0,
FMT_CONTROL,
FMT_SUBSAMPLING_ORDER);
}
if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
set_reg_field_value(fmt_cntl_value,
2,
FMT_CONTROL,
FMT_PIXEL_ENCODING);
/* 02 - Subsampling mode, 3 taps*/
set_reg_field_value(fmt_cntl_value,
2,
FMT_CONTROL,
FMT_SUBSAMPLING_MODE);
/* 00 - Enable CbCr bit reduction bypass to preserve precision*/
set_reg_field_value(fmt_cntl_value,
1,
FMT_CONTROL,
FMT_CBCR_BIT_REDUCTION_BYPASS);
}
dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value);
}
void dce112_opp_program_clamping_and_pixel_encoding(
struct output_pixel_processor *opp,
const struct clamping_and_pixel_encoding_params *params)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
dce110_opp_set_clamping(opp110, params);
set_pixel_encoding(opp110, params);
}
static void program_formatter_420_memory(struct output_pixel_processor *opp)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
uint32_t fmt_cntl_value;
uint32_t fmt_mem_cntl_value;
uint32_t fmt_cntl_addr = FMT_REG(mmFMT_CONTROL);
uint32_t fmt_mem_cntl_addr = FMT_MEM_REG(mmFMT_MEMORY0_CONTROL);
fmt_mem_cntl_value = dm_read_reg(opp110->base.ctx, fmt_mem_cntl_addr);
fmt_cntl_value = dm_read_reg(opp110->base.ctx, fmt_cntl_addr);
/* Program source select*/
/* Use HW default source select for FMT_MEMORYx_CONTROL */
/* Use that value for FMT_SRC_SELECT as well*/
set_reg_field_value(fmt_cntl_value,
get_reg_field_value(fmt_mem_cntl_value, FMT_MEMORY0_CONTROL, FMT420_MEM0_SOURCE_SEL),
FMT_CONTROL,
FMT_SRC_SELECT);
dm_write_reg(opp110->base.ctx, fmt_cntl_addr, fmt_cntl_value);
/* Turn on the memory */
set_reg_field_value(fmt_mem_cntl_value,
0,
FMT_MEMORY0_CONTROL,
FMT420_MEM0_PWR_FORCE);
dm_write_reg(opp110->base.ctx, fmt_mem_cntl_addr, fmt_mem_cntl_value);
}
static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
uint32_t value;
uint32_t addr = FMT_REG(mmFMT_CONTROL);
uint8_t counter = 10;
value = dm_read_reg(opp110->base.ctx, addr);
/* clear previous phase lock status*/
set_reg_field_value(value,
1,
FMT_CONTROL,
FMT_420_PIXEL_PHASE_LOCKED_CLEAR);
dm_write_reg(opp110->base.ctx, addr, value);
/* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/
while (counter > 0) {
value = dm_read_reg(opp110->base.ctx, addr);
if (get_reg_field_value(
value,
FMT_CONTROL,
FMT_420_PIXEL_PHASE_LOCKED) == 1)
break;
msleep(10);
counter--;
}
if (counter == 0)
dm_logger_write(opp->ctx->logger, LOG_ERROR,
"%s:opp program formattter reset dig resync info time out.\n",
__func__);
}
void dce112_opp_program_fmt(
struct output_pixel_processor *opp,
struct bit_depth_reduction_params *fmt_bit_depth,
struct clamping_and_pixel_encoding_params *clamping)
{
/* dithering is affected by <CrtcSourceSelect>, hence should be
* programmed afterwards */
if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
program_formatter_420_memory(opp);
dce110_opp_program_bit_depth_reduction(
opp,
fmt_bit_depth);
dce112_opp_program_clamping_and_pixel_encoding(
opp,
clamping);
if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
program_formatter_reset_dig_resync_fifo(opp);
return;
}
......@@ -39,7 +39,7 @@
#include "dce/dce_link_encoder.h"
#include "dce/dce_stream_encoder.h"
#include "dce/dce_audio.h"
#include "dce112/dce112_opp.h"
#include "dce/dce_opp.h"
#include "dce110/dce110_ipp.h"
#include "dce/dce_clocks.h"
#include "dce/dce_clock_source.h"
......@@ -306,6 +306,28 @@ static const struct dce_stream_encoder_mask se_mask = {
SE_COMMON_MASK_SH_LIST_DCE112(_MASK)
};
#define opp_regs(id)\
[id] = {\
OPP_DCE_112_REG_LIST(id),\
}
static const struct dce_opp_registers opp_regs[] = {
opp_regs(0),
opp_regs(1),
opp_regs(2),
opp_regs(3),
opp_regs(4),
opp_regs(5)
};
static const struct dce_opp_shift opp_shift = {
OPP_COMMON_MASK_SH_LIST_DCE_112(__SHIFT)
};
static const struct dce_opp_mask opp_mask = {
OPP_COMMON_MASK_SH_LIST_DCE_112(_MASK)
};
#define audio_regs(id)\
[id] = {\
AUD_COMMON_REG_LIST(id)\
......@@ -328,42 +350,6 @@ static const struct dce_aduio_mask audio_mask = {
AUD_COMMON_MASK_SH_LIST(_MASK)
};
static const struct dce110_opp_reg_offsets dce112_opp_reg_offsets[] = {
{
.fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.fmt_mem_offset = (mmFMT_MEMORY0_CONTROL - mmFMT_MEMORY0_CONTROL),
.dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
.dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.fmt_mem_offset = (mmFMT_MEMORY1_CONTROL - mmFMT_MEMORY0_CONTROL),
.dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
.dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.fmt_mem_offset = (mmFMT_MEMORY2_CONTROL - mmFMT_MEMORY0_CONTROL),
.dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
.dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{
.fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.fmt_mem_offset = (mmFMT_MEMORY3_CONTROL - mmFMT_MEMORY0_CONTROL),
.dcfe_offset = (mmDCFE3_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
.dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.fmt_mem_offset = (mmFMT_MEMORY4_CONTROL - mmFMT_MEMORY0_CONTROL),
.dcfe_offset = (mmDCFE4_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
.dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.fmt_mem_offset = (mmFMT_MEMORY5_CONTROL - mmFMT_MEMORY0_CONTROL),
.dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
.dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
}
};
#define clk_src_regs(index, id)\
[index] = {\
CS_COMMON_REG_LIST_DCE_112(id),\
......@@ -631,8 +617,7 @@ void dce112_ipp_destroy(struct input_pixel_processor **ipp)
struct output_pixel_processor *dce112_opp_create(
struct dc_context *ctx,
uint32_t inst,
const struct dce110_opp_reg_offsets *offset)
uint32_t inst)
{
struct dce110_opp *opp =
dm_alloc(sizeof(struct dce110_opp));
......@@ -640,8 +625,8 @@ struct output_pixel_processor *dce112_opp_create(
if (!opp)
return NULL;
if (dce112_opp_construct(opp,
ctx, inst, offset))
if (dce110_opp_construct(opp,
ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask))
return &opp->base;
BREAK_TO_DEBUGGER();
......@@ -1381,8 +1366,7 @@ static bool construct(
pool->base.opps[i] = dce112_opp_create(
ctx,
i,
&dce112_opp_reg_offsets[i]);
i);
if (pool->base.opps[i] == NULL) {
BREAK_TO_DEBUGGER();
dm_error(
......
......@@ -2,9 +2,8 @@
# Makefile for the 'controller' sub-component of DAL.
# It provides the control and status of HW CRTC block.
DCE80 = dce80_ipp.o dce80_ipp_gamma.o dce80_opp.o \
dce80_opp_formatter.o dce80_opp_regamma.o \
dce80_timing_generator.o dce80_opp_csc.o\
DCE80 = dce80_ipp.o dce80_ipp_gamma.o \
dce80_timing_generator.o \
dce80_compressor.o dce80_mem_input.o dce80_hw_sequencer.o \
dce80_resource.o
......
/*
* Copyright 2012-15 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 "dm_services.h"
/* include DCE8 register header files */
#include "dce/dce_8_0_d.h"
#include "dce/dce_8_0_sh_mask.h"
#include "dce80_opp.h"
#define FROM_OPP(opp)\
container_of(opp, struct dce80_opp, base)
enum {
MAX_LUT_ENTRY = 256,
MAX_NUMBER_OF_ENTRIES = 256
};
static const struct dce80_opp_reg_offsets reg_offsets[] = {
{
.fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.crtc_offset = (mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL -
mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
.dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.crtc_offset = (mmCRTC1_DCFE_MEM_LIGHT_SLEEP_CNTL -
mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
.dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.crtc_offset = (mmCRTC2_DCFE_MEM_LIGHT_SLEEP_CNTL -
mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
.dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{
.fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.crtc_offset = (mmCRTC3_DCFE_MEM_LIGHT_SLEEP_CNTL -
mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
.dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{
.fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.crtc_offset = (mmCRTC4_DCFE_MEM_LIGHT_SLEEP_CNTL -
mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
.dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
},
{
.fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL),
.crtc_offset = (mmCRTC5_DCFE_MEM_LIGHT_SLEEP_CNTL -
mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL),
.dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
}
};
static const struct opp_funcs funcs = {
.opp_power_on_regamma_lut = dce80_opp_power_on_regamma_lut,
.opp_set_csc_adjustment = dce80_opp_set_csc_adjustment,
.opp_set_csc_default = dce80_opp_set_csc_default,
.opp_set_dyn_expansion = dce80_opp_set_dyn_expansion,
.opp_program_regamma_pwl = dce80_opp_program_regamma_pwl,
.opp_set_regamma_mode = dce80_opp_set_regamma_mode,
.opp_destroy = dce80_opp_destroy,
.opp_program_fmt = dce110_opp_program_fmt,
};
/*****************************************/
/* Constructor, Destructor */
/*****************************************/
bool dce80_opp_construct(struct dce80_opp *opp80,
struct dc_context *ctx,
uint32_t inst)
{
if (inst >= ARRAY_SIZE(reg_offsets))
return false;
opp80->base.funcs = &funcs;
opp80->base.ctx = ctx;
opp80->base.inst = inst;
opp80->offsets = reg_offsets[inst];
return true;
}
void dce80_opp_destroy(struct output_pixel_processor **opp)
{
dm_free(FROM_OPP(*opp));
*opp = NULL;
}
struct output_pixel_processor *dce80_opp_create(
struct dc_context *ctx,
uint32_t inst)
{
struct dce80_opp *opp =
dm_alloc(sizeof(struct dce80_opp));
if (!opp)
return NULL;
if (dce80_opp_construct(opp,
ctx, inst))
return &opp->base;
BREAK_TO_DEBUGGER();
dm_free(opp);
return NULL;
}
/* Copyright 2012-15 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 __DC_OPP_DCE80_H__
#define __DC_OPP_DCE80_H__
#include "dc_types.h"
#include "opp.h"
#include "gamma_types.h"
#include "../dce110/dce110_opp.h"
struct gamma_parameters;
struct dce80_regamma {
struct gamma_curve arr_curve_points[16];
struct curve_points arr_points[3];
uint32_t hw_points_num;
struct hw_x_point *coordinates_x;
struct pwl_result_data *rgb_resulted;
/* re-gamma curve */
struct pwl_float_data_ex *rgb_regamma;
/* coeff used to map user evenly distributed points
* to our hardware points (predefined) for gamma 256 */
struct pixel_gamma_point *coeff128;
struct pixel_gamma_point *coeff128_oem;
/* coeff used to map user evenly distributed points
* to our hardware points (predefined) for gamma 1025 */
struct pixel_gamma_point *coeff128_dx;
/* evenly distributed points, gamma 256 software points 0-255 */
struct gamma_pixel *axis_x_256;
/* evenly distributed points, gamma 1025 software points 0-1025 */
struct gamma_pixel *axis_x_1025;
/* OEM supplied gamma for regamma LUT */
struct pwl_float_data *rgb_oem;
/* user supplied gamma */
struct pwl_float_data *rgb_user;
uint32_t extra_points;
bool use_half_points;
struct fixed31_32 x_max1;
struct fixed31_32 x_max2;
struct fixed31_32 x_min;
struct fixed31_32 divider1;
struct fixed31_32 divider2;
struct fixed31_32 divider3;
};
/* OPP RELATED */
#define TO_DCE80_OPP(opp)\
container_of(opp, struct dce80_opp, base)
struct dce80_opp_reg_offsets {
uint32_t fmt_offset;
uint32_t dcp_offset;
uint32_t crtc_offset;
};
struct dce80_opp {
struct output_pixel_processor base;
struct dce80_opp_reg_offsets offsets;
struct dce80_regamma regamma;
};
bool dce80_opp_construct(struct dce80_opp *opp80,
struct dc_context *ctx,
uint32_t inst);
void dce80_opp_destroy(struct output_pixel_processor **opp);
struct output_pixel_processor *dce80_opp_create(
struct dc_context *ctx,
uint32_t inst);
/* REGAMMA RELATED */
void dce80_opp_power_on_regamma_lut(
struct output_pixel_processor *opp,
bool power_on);
bool dce80_opp_program_regamma_pwl(
struct output_pixel_processor *opp,
const struct pwl_params *pamras);
void dce80_opp_set_regamma_mode(struct output_pixel_processor *opp,
enum opp_regamma mode);
void dce80_opp_set_csc_adjustment(
struct output_pixel_processor *opp,
const struct out_csc_color_matrix *tbl_entry);
void dce80_opp_set_csc_default(
struct output_pixel_processor *opp,
const struct default_adjustment *default_adjust);
/* FORMATTER RELATED */
void dce80_opp_program_bit_depth_reduction(
struct output_pixel_processor *opp,
const struct bit_depth_reduction_params *params);
void dce80_opp_program_clamping_and_pixel_encoding(
struct output_pixel_processor *opp,
const struct clamping_and_pixel_encoding_params *params);
void dce80_opp_set_dyn_expansion(
struct output_pixel_processor *opp,
enum dc_color_space color_sp,
enum dc_color_depth color_dpth,
enum signal_type signal);
#endif
/*
* Copyright 2012-15 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 "dm_services.h"
#include "dce80_opp.h"
#include "basics/conversion.h"
/* include DCE8 register header files */
#include "dce/dce_8_0_d.h"
#include "dce/dce_8_0_sh_mask.h"
#define DCP_REG(reg)\
(reg + opp80->offsets.dcp_offset)
enum {
OUTPUT_CSC_MATRIX_SIZE = 12
};
static const struct out_csc_color_matrix global_color_matrix[] = {
{ COLOR_SPACE_SRGB,
{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
{ COLOR_SPACE_SRGB_LIMITED,
{ 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} },
{ COLOR_SPACE_YCBCR601,
{ 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47,
0xF6B9, 0xE00, 0x1000} },
{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA,
0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
/* TODO: correct values below */
{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }
};
enum csc_color_mode {
/* 00 - BITS2:0 Bypass */
CSC_COLOR_MODE_GRAPHICS_BYPASS,
/* 01 - hard coded coefficient TV RGB */
CSC_COLOR_MODE_GRAPHICS_PREDEFINED,
/* 04 - programmable OUTPUT CSC coefficient */
CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC,
};
static void program_color_matrix(
struct dce80_opp *opp80,
const struct out_csc_color_matrix *tbl_entry,
enum grph_color_adjust_option options)
{
struct dc_context *ctx = opp80->base.ctx;
{
uint32_t value = 0;
uint32_t addr = DCP_REG(mmOUTPUT_CSC_C11_C12);
/* fixed S2.13 format */
set_reg_field_value(
value,
tbl_entry->regval[0],
OUTPUT_CSC_C11_C12,
OUTPUT_CSC_C11);
set_reg_field_value(
value,
tbl_entry->regval[1],
OUTPUT_CSC_C11_C12,
OUTPUT_CSC_C12);
dm_write_reg(ctx, addr, value);
}
{
uint32_t value = 0;
uint32_t addr = DCP_REG(mmOUTPUT_CSC_C13_C14);
/* fixed S2.13 format */
set_reg_field_value(
value,
tbl_entry->regval[2],
OUTPUT_CSC_C13_C14,
OUTPUT_CSC_C13);
/* fixed S0.13 format */
set_reg_field_value(
value,
tbl_entry->regval[3],
OUTPUT_CSC_C13_C14,
OUTPUT_CSC_C14);
dm_write_reg(ctx, addr, value);
}
{
uint32_t value = 0;
uint32_t addr = DCP_REG(mmOUTPUT_CSC_C21_C22);
/* fixed S2.13 format */
set_reg_field_value(
value,
tbl_entry->regval[4],
OUTPUT_CSC_C21_C22,
OUTPUT_CSC_C21);
/* fixed S2.13 format */
set_reg_field_value(
value,
tbl_entry->regval[5],
OUTPUT_CSC_C21_C22,
OUTPUT_CSC_C22);
dm_write_reg(ctx, addr, value);
}
{
uint32_t value = 0;
uint32_t addr = DCP_REG(mmOUTPUT_CSC_C23_C24);
/* fixed S2.13 format */
set_reg_field_value(
value,
tbl_entry->regval[6],
OUTPUT_CSC_C23_C24,
OUTPUT_CSC_C23);
/* fixed S0.13 format */
set_reg_field_value(
value,
tbl_entry->regval[7],
OUTPUT_CSC_C23_C24,
OUTPUT_CSC_C24);
dm_write_reg(ctx, addr, value);
}
{
uint32_t value = 0;
uint32_t addr = DCP_REG(mmOUTPUT_CSC_C31_C32);
/* fixed S2.13 format */
set_reg_field_value(
value,
tbl_entry->regval[8],
OUTPUT_CSC_C31_C32,
OUTPUT_CSC_C31);
/* fixed S0.13 format */
set_reg_field_value(
value,
tbl_entry->regval[9],
OUTPUT_CSC_C31_C32,
OUTPUT_CSC_C32);
dm_write_reg(ctx, addr, value);
}
{
uint32_t value = 0;
uint32_t addr = DCP_REG(mmOUTPUT_CSC_C33_C34);
/* fixed S2.13 format */
set_reg_field_value(
value,
tbl_entry->regval[10],
OUTPUT_CSC_C33_C34,
OUTPUT_CSC_C33);
/* fixed S0.13 format */
set_reg_field_value(
value,
tbl_entry->regval[11],
OUTPUT_CSC_C33_C34,
OUTPUT_CSC_C34);
dm_write_reg(ctx, addr, value);
}
}
static bool configure_graphics_mode(
struct dce80_opp *opp80,
enum csc_color_mode config,
enum graphics_csc_adjust_type csc_adjust_type,
enum dc_color_space color_space)
{
struct dc_context *ctx = opp80->base.ctx;
uint32_t addr = DCP_REG(mmOUTPUT_CSC_CONTROL);
uint32_t value = dm_read_reg(ctx, addr);
set_reg_field_value(
value,
0,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) {
if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) {
set_reg_field_value(
value,
4,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
} else {
switch (color_space) {
case COLOR_SPACE_SRGB:
/* by pass */
set_reg_field_value(
value,
0,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
case COLOR_SPACE_SRGB_LIMITED:
/* TV RGB */
set_reg_field_value(
value,
1,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
case COLOR_SPACE_YCBCR601:
case COLOR_SPACE_YPBPR601:
case COLOR_SPACE_YCBCR601_LIMITED:
/* YCbCr601 */
set_reg_field_value(
value,
2,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
case COLOR_SPACE_YCBCR709:
case COLOR_SPACE_YPBPR709:
case COLOR_SPACE_YCBCR709_LIMITED:
/* YCbCr709 */
set_reg_field_value(
value,
3,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
default:
return false;
}
}
} else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) {
switch (color_space) {
case COLOR_SPACE_SRGB:
/* by pass */
set_reg_field_value(
value,
0,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
case COLOR_SPACE_SRGB_LIMITED:
/* TV RGB */
set_reg_field_value(
value,
1,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
case COLOR_SPACE_YCBCR601:
case COLOR_SPACE_YPBPR601:
case COLOR_SPACE_YCBCR601_LIMITED:
/* YCbCr601 */
set_reg_field_value(
value,
2,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
case COLOR_SPACE_YCBCR709:
case COLOR_SPACE_YPBPR709:
case COLOR_SPACE_YCBCR709_LIMITED:
/* YCbCr709 */
set_reg_field_value(
value,
3,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
break;
default:
return false;
}
} else
/* by pass */
set_reg_field_value(
value,
0,
OUTPUT_CSC_CONTROL,
OUTPUT_CSC_GRPH_MODE);
addr = DCP_REG(mmOUTPUT_CSC_CONTROL);
dm_write_reg(ctx, addr, value);
return true;
}
void dce80_opp_set_csc_adjustment(
struct output_pixel_processor *opp,
const struct out_csc_color_matrix *tbl_entry)
{
struct dce80_opp *opp80 = TO_DCE80_OPP(opp);
enum csc_color_mode config =
CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
program_color_matrix(opp80, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW);
/* We did everything ,now program DxOUTPUT_CSC_CONTROL */
configure_graphics_mode(opp80, config, GRAPHICS_CSC_ADJUST_TYPE_SW,
tbl_entry->color_space);
}
void dce80_opp_set_csc_default(
struct output_pixel_processor *opp,
const struct default_adjustment *default_adjust)
{
struct dce80_opp *opp80 = TO_DCE80_OPP(opp);
enum csc_color_mode config =
CSC_COLOR_MODE_GRAPHICS_PREDEFINED;
if (default_adjust->force_hw_default == false) {
const struct out_csc_color_matrix *elm;
/* currently parameter not in use */
enum grph_color_adjust_option option =
GRPH_COLOR_MATRIX_HW_DEFAULT;
uint32_t i;
/*
* HW default false we program locally defined matrix
* HW default true we use predefined hw matrix and we
* do not need to program matrix
* OEM wants the HW default via runtime parameter.
*/
option = GRPH_COLOR_MATRIX_SW;
for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) {
elm = &global_color_matrix[i];
if (elm->color_space != default_adjust->out_color_space)
continue;
/* program the matrix with default values from this
* file */
program_color_matrix(opp80, elm, option);
config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
break;
}
}
/* configure the what we programmed :
* 1. Default values from this file
* 2. Use hardware default from ROM_A and we do not need to program
* matrix */
configure_graphics_mode(opp80, config,
default_adjust->csc_adjust_type,
default_adjust->out_color_space);
}
/*
* Copyright 2012-15 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 "dm_services.h"
#include "dce/dce_8_0_d.h"
#include "dce/dce_8_0_sh_mask.h"
#include "dce80_opp.h"
#define FMT_REG(reg)\
(reg + opp80->offsets.fmt_offset)
/**
* set_truncation
* 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
* 2) enable truncation
* 3) HW remove 12bit FMT support for DCE8 power saving reason.
*/
static void set_truncation(
struct dce80_opp *opp80,
const struct bit_depth_reduction_params *params)
{
uint32_t value = 0;
uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
/*Disable truncation*/
value = dm_read_reg(opp80->base.ctx, addr);
set_reg_field_value(value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN);
set_reg_field_value(value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH);
set_reg_field_value(value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE);
dm_write_reg(opp80->base.ctx, addr, value);
/* no 10bpc trunc on DCE8*/
if (params->flags.TRUNCATE_ENABLED == 0 ||
params->flags.TRUNCATE_DEPTH == 2)
return;
/*Set truncation depth and Enable truncation*/
set_reg_field_value(value, 1,
FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN);
set_reg_field_value(value, params->flags.TRUNCATE_MODE,
FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE);
set_reg_field_value(value, params->flags.TRUNCATE_DEPTH,
FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH);
dm_write_reg(opp80->base.ctx, addr, value);
}
/**
* set_spatial_dither
* 1) set spatial dithering mode: pattern of seed
* 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp
* 3) set random seed
* 4) set random mode
* lfsr is reset every frame or not reset
* RGB dithering method
* 0: RGB data are all dithered with x^28+x^3+1
* 1: R data is dithered with x^28+x^3+1
* G data is dithered with x^28+X^9+1
* B data is dithered with x^28+x^13+1
* enable high pass filter or not
* 5) enable spatical dithering
*/
static void set_spatial_dither(
struct dce80_opp *opp80,
const struct bit_depth_reduction_params *params)
{
uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
uint32_t depth_cntl_value = 0;
uint32_t dither_r_value = 0;
uint32_t dither_g_value = 0;
uint32_t dither_b_value = 0;
/*Disable spatial (random) dithering*/
depth_cntl_value = dm_read_reg(opp80->base.ctx, addr);
set_reg_field_value(depth_cntl_value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN);
set_reg_field_value(depth_cntl_value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE);
set_reg_field_value(depth_cntl_value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH);
set_reg_field_value(depth_cntl_value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN);
set_reg_field_value(depth_cntl_value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE);
set_reg_field_value(depth_cntl_value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE);
set_reg_field_value(depth_cntl_value, 0,
FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE);
dm_write_reg(opp80->base.ctx, addr, depth_cntl_value);
/* no 10bpc on DCE8*/
if (params->flags.SPATIAL_DITHER_ENABLED == 0 ||
params->flags.SPATIAL_DITHER_DEPTH == 2)
return;
/*Set seed for random values for
* spatial dithering for R,G,B channels*/
addr = FMT_REG(mmFMT_DITHER_RAND_R_SEED);
set_reg_field_value(dither_r_value, params->r_seed_value,
FMT_DITHER_RAND_R_SEED,
FMT_RAND_R_SEED);
dm_write_reg(opp80->base.ctx, addr, dither_r_value);
addr = FMT_REG(mmFMT_DITHER_RAND_G_SEED);
set_reg_field_value(dither_g_value,
params->g_seed_value,
FMT_DITHER_RAND_G_SEED,
FMT_RAND_G_SEED);
dm_write_reg(opp80->base.ctx, addr, dither_g_value);
addr = FMT_REG(mmFMT_DITHER_RAND_B_SEED);
set_reg_field_value(dither_b_value, params->b_seed_value,
FMT_DITHER_RAND_B_SEED,
FMT_RAND_B_SEED);
dm_write_reg(opp80->base.ctx, addr, dither_b_value);
/* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero
* offset for the R/Cr channel, lower 4LSB
* is forced to zeros. Typically set to 0
* RGB and 0x80000 YCbCr.
*/
/* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero
* offset for the G/Y channel, lower 4LSB is
* forced to zeros. Typically set to 0 RGB
* and 0x80000 YCbCr.
*/
/* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero
* offset for the B/Cb channel, lower 4LSB is
* forced to zeros. Typically set to 0 RGB and
* 0x80000 YCbCr.
*/
/*Set spatial dithering bit depth*/
set_reg_field_value(depth_cntl_value,
params->flags.SPATIAL_DITHER_DEPTH,
FMT_BIT_DEPTH_CONTROL,
FMT_SPATIAL_DITHER_DEPTH);
/* Set spatial dithering mode
* (default is Seed patterrn AAAA...)
*/
set_reg_field_value(depth_cntl_value,
params->flags.SPATIAL_DITHER_MODE,
FMT_BIT_DEPTH_CONTROL,
FMT_SPATIAL_DITHER_MODE);
/*Reset only at startup*/
set_reg_field_value(depth_cntl_value,
params->flags.FRAME_RANDOM,
FMT_BIT_DEPTH_CONTROL,
FMT_FRAME_RANDOM_ENABLE);
/*Set RGB data dithered with x^28+x^3+1*/
set_reg_field_value(depth_cntl_value,
params->flags.RGB_RANDOM,
FMT_BIT_DEPTH_CONTROL,
FMT_RGB_RANDOM_ENABLE);
/*Disable High pass filter*/
set_reg_field_value(depth_cntl_value,
params->flags.HIGHPASS_RANDOM,
FMT_BIT_DEPTH_CONTROL,
FMT_HIGHPASS_RANDOM_ENABLE);
/*Enable spatial dithering*/
set_reg_field_value(depth_cntl_value,
1,
FMT_BIT_DEPTH_CONTROL,
FMT_SPATIAL_DITHER_EN);
addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
dm_write_reg(opp80->base.ctx, addr, depth_cntl_value);
}
/**
* SetTemporalDither (Frame Modulation)
* 1) set temporal dither depth
* 2) select pattern: from hard-coded pattern or programmable pattern
* 3) select optimized strips for BGR or RGB LCD sub-pixel
* 4) set s matrix
* 5) set t matrix
* 6) set grey level for 0.25, 0.5, 0.75
* 7) enable temporal dithering
*/
static void set_temporal_dither(
struct dce80_opp *opp80,
const struct bit_depth_reduction_params *params)
{
uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
uint32_t value;
/*Disable temporal (frame modulation) dithering first*/
value = dm_read_reg(opp80->base.ctx, addr);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_EN);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_RESET);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_OFFSET);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_DEPTH);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_LEVEL);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_25FRC_SEL);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_50FRC_SEL);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_75FRC_SEL);
dm_write_reg(opp80->base.ctx, addr, value);
/* no 10bpc dither on DCE8*/
if (params->flags.FRAME_MODULATION_ENABLED == 0 ||
params->flags.FRAME_MODULATION_DEPTH == 2)
return;
/* Set temporal dithering depth*/
set_reg_field_value(value,
params->flags.FRAME_MODULATION_DEPTH,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_DEPTH);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_RESET);
set_reg_field_value(value,
0,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_OFFSET);
/*Select legacy pattern based on FRC and Temporal level*/
addr = FMT_REG(mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL);
dm_write_reg(opp80->base.ctx, addr, 0);
/*Set s matrix*/
addr = FMT_REG(
mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX);
dm_write_reg(opp80->base.ctx, addr, 0);
/*Set t matrix*/
addr = FMT_REG(
mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX);
dm_write_reg(opp80->base.ctx, addr, 0);
/*Select patterns for 0.25, 0.5 and 0.75 grey level*/
set_reg_field_value(value,
params->flags.TEMPORAL_LEVEL,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_LEVEL);
set_reg_field_value(value,
params->flags.FRC25,
FMT_BIT_DEPTH_CONTROL,
FMT_25FRC_SEL);
set_reg_field_value(value,
params->flags.FRC50,
FMT_BIT_DEPTH_CONTROL,
FMT_50FRC_SEL);
set_reg_field_value(value,
params->flags.FRC75,
FMT_BIT_DEPTH_CONTROL,
FMT_75FRC_SEL);
/*Enable bit reduction by temporal (frame modulation) dithering*/
set_reg_field_value(value,
1,
FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_EN);
addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
dm_write_reg(opp80->base.ctx, addr, value);
}
/**
* Set Clamping
* 1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
* 1 for 8 bpc
* 2 for 10 bpc
* 3 for 12 bpc
* 7 for programable
* 2) Enable clamp if Limited range requested
*/
static void set_clamping(
struct dce80_opp *opp80,
const struct clamping_and_pixel_encoding_params *params)
{
uint32_t clamp_cntl_value = 0;
uint32_t red_clamp_value = 0;
uint32_t green_clamp_value = 0;
uint32_t blue_clamp_value = 0;
uint32_t addr = FMT_REG(mmFMT_CLAMP_CNTL);
clamp_cntl_value = dm_read_reg(opp80->base.ctx, addr);
set_reg_field_value(clamp_cntl_value,
0,
FMT_CLAMP_CNTL,
FMT_CLAMP_DATA_EN);
set_reg_field_value(clamp_cntl_value,
0,
FMT_CLAMP_CNTL,
FMT_CLAMP_COLOR_FORMAT);
switch (params->clamping_level) {
case CLAMPING_FULL_RANGE:
break;
case CLAMPING_LIMITED_RANGE_8BPC:
set_reg_field_value(clamp_cntl_value,
1,
FMT_CLAMP_CNTL,
FMT_CLAMP_DATA_EN);
set_reg_field_value(clamp_cntl_value,
1,
FMT_CLAMP_CNTL,
FMT_CLAMP_COLOR_FORMAT);
break;
case CLAMPING_LIMITED_RANGE_10BPC:
set_reg_field_value(clamp_cntl_value,
1,
FMT_CLAMP_CNTL,
FMT_CLAMP_DATA_EN);
set_reg_field_value(clamp_cntl_value,
2,
FMT_CLAMP_CNTL,
FMT_CLAMP_COLOR_FORMAT);
break;
case CLAMPING_LIMITED_RANGE_12BPC:
set_reg_field_value(clamp_cntl_value,
1,
FMT_CLAMP_CNTL,
FMT_CLAMP_DATA_EN);
set_reg_field_value(clamp_cntl_value,
3,
FMT_CLAMP_CNTL,
FMT_CLAMP_COLOR_FORMAT);
break;
case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
set_reg_field_value(clamp_cntl_value,
1,
FMT_CLAMP_CNTL,
FMT_CLAMP_DATA_EN);
set_reg_field_value(clamp_cntl_value,
7,
FMT_CLAMP_CNTL,
FMT_CLAMP_COLOR_FORMAT);
/*set the defaults*/
set_reg_field_value(red_clamp_value,
0x10,
FMT_CLAMP_COMPONENT_R,
FMT_CLAMP_LOWER_R);
set_reg_field_value(red_clamp_value,
0xFEF,
FMT_CLAMP_COMPONENT_R,
FMT_CLAMP_UPPER_R);
addr = FMT_REG(mmFMT_CLAMP_COMPONENT_R);
dm_write_reg(opp80->base.ctx, addr, red_clamp_value);
set_reg_field_value(green_clamp_value,
0x10,
FMT_CLAMP_COMPONENT_G,
FMT_CLAMP_LOWER_G);
set_reg_field_value(green_clamp_value,
0xFEF,
FMT_CLAMP_COMPONENT_G,
FMT_CLAMP_UPPER_G);
addr = FMT_REG(mmFMT_CLAMP_COMPONENT_G);
dm_write_reg(opp80->base.ctx, addr, green_clamp_value);
set_reg_field_value(blue_clamp_value,
0x10,
FMT_CLAMP_COMPONENT_B,
FMT_CLAMP_LOWER_B);
set_reg_field_value(blue_clamp_value,
0xFEF,
FMT_CLAMP_COMPONENT_B,
FMT_CLAMP_UPPER_B);
addr = FMT_REG(mmFMT_CLAMP_COMPONENT_B);
dm_write_reg(opp80->base.ctx, addr, blue_clamp_value);
break;
default:
break;
}
addr = FMT_REG(mmFMT_CLAMP_CNTL);
/*Set clamp control*/
dm_write_reg(opp80->base.ctx, addr, clamp_cntl_value);
}
/**
* set_pixel_encoding
*
* Set Pixel Encoding
* 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
* 1: YCbCr 4:2:2
*/
static void set_pixel_encoding(
struct dce80_opp *opp80,
const struct clamping_and_pixel_encoding_params *params)
{
uint32_t fmt_cntl_value;
uint32_t addr = FMT_REG(mmFMT_CONTROL);
/*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/
fmt_cntl_value = dm_read_reg(opp80->base.ctx, addr);
set_reg_field_value(fmt_cntl_value,
0,
FMT_CONTROL,
FMT_PIXEL_ENCODING);
if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
set_reg_field_value(fmt_cntl_value,
1,
FMT_CONTROL,
FMT_PIXEL_ENCODING);
/*00 - Pixels drop mode ,01 - Pixels average mode*/
set_reg_field_value(fmt_cntl_value,
0,
FMT_CONTROL,
FMT_SUBSAMPLING_MODE);
/*00 - Cb before Cr ,01 - Cr before Cb*/
set_reg_field_value(fmt_cntl_value,
0,
FMT_CONTROL,
FMT_SUBSAMPLING_ORDER);
}
dm_write_reg(opp80->base.ctx, addr, fmt_cntl_value);
}
void dce80_opp_program_bit_depth_reduction(
struct output_pixel_processor *opp,
const struct bit_depth_reduction_params *params)
{
struct dce80_opp *opp80 = TO_DCE80_OPP(opp);
set_truncation(opp80, params);
set_spatial_dither(opp80, params);
set_temporal_dither(opp80, params);
}
void dce80_opp_program_clamping_and_pixel_encoding(
struct output_pixel_processor *opp,
const struct clamping_and_pixel_encoding_params *params)
{
struct dce80_opp *opp80 = TO_DCE80_OPP(opp);
set_clamping(opp80, params);
set_pixel_encoding(opp80, params);
}
void dce80_opp_set_dyn_expansion(
struct output_pixel_processor *opp,
enum dc_color_space color_sp,
enum dc_color_depth color_dpth,
enum signal_type signal)
{
struct dce80_opp *opp80 = TO_DCE80_OPP(opp);
uint32_t value;
bool enable_dyn_exp = false;
uint32_t addr = FMT_REG(mmFMT_DYNAMIC_EXP_CNTL);
value = dm_read_reg(opp->ctx, addr);
set_reg_field_value(value, 0,
FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN);
set_reg_field_value(value, 0,
FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE);
/* From HW programming guide:
FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output
FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/
if (color_sp == COLOR_SPACE_SRGB)
enable_dyn_exp = true;
/*00 - 10-bit -> 12-bit dynamic expansion*/
/*01 - 8-bit -> 12-bit dynamic expansion*/
if (signal == SIGNAL_TYPE_HDMI_TYPE_A) {
switch (color_dpth) {
case COLOR_DEPTH_888:
set_reg_field_value(value, enable_dyn_exp ? 1:0,
FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN);
set_reg_field_value(value, 1,
FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE);
break;
case COLOR_DEPTH_101010:
set_reg_field_value(value, enable_dyn_exp ? 1:0,
FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN);
set_reg_field_value(value, 0,
FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE);
break;
case COLOR_DEPTH_121212:
break;
default:
break;
}
}
dm_write_reg(opp->ctx, addr, value);
}
/*
* Copyright 2012-15 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 "dm_services.h"
/* include DCE8 register header files */
#include "dce/dce_8_0_d.h"
#include "dce/dce_8_0_sh_mask.h"
#include "dce80_opp.h"
#include "gamma_types.h"
#define DCP_REG(reg)\
(reg + opp80->offsets.dcp_offset)
#define DCFE_REG(reg)\
(reg + opp80->offsets.crtc_offset)
enum {
MAX_PWL_ENTRY = 128,
MAX_REGIONS_NUMBER = 16
};
struct curve_config {
uint32_t offset;
int8_t segments[MAX_REGIONS_NUMBER];
int8_t begin;
};
/*
*****************************************************************************
* Function: regamma_config_regions_and_segments
*
* build regamma curve by using predefined hw points
* uses interface parameters ,like EDID coeff.
*
* @param : parameters interface parameters
* @return void
*
* @note
*
* @see
*
*****************************************************************************
*/
static void regamma_config_regions_and_segments(
struct dce80_opp *opp80, const struct pwl_params *params)
{
const struct gamma_curve *curve;
uint32_t value = 0;
{
set_reg_field_value(
value,
params->arr_points[0].custom_float_x,
REGAMMA_CNTLA_START_CNTL,
REGAMMA_CNTLA_EXP_REGION_START);
set_reg_field_value(
value,
0,
REGAMMA_CNTLA_START_CNTL,
REGAMMA_CNTLA_EXP_REGION_START_SEGMENT);
dm_write_reg(opp80->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_START_CNTL),
value);
}
{
value = 0;
set_reg_field_value(
value,
params->arr_points[0].custom_float_slope,
REGAMMA_CNTLA_SLOPE_CNTL,
REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE);
dm_write_reg(opp80->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_SLOPE_CNTL), value);
}
{
value = 0;
set_reg_field_value(
value,
params->arr_points[1].custom_float_x,
REGAMMA_CNTLA_END_CNTL1,
REGAMMA_CNTLA_EXP_REGION_END);
dm_write_reg(opp80->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_END_CNTL1), value);
}
{
value = 0;
set_reg_field_value(
value,
params->arr_points[2].custom_float_slope,
REGAMMA_CNTLA_END_CNTL2,
REGAMMA_CNTLA_EXP_REGION_END_BASE);
set_reg_field_value(
value,
params->arr_points[1].custom_float_y,
REGAMMA_CNTLA_END_CNTL2,
REGAMMA_CNTLA_EXP_REGION_END_SLOPE);
dm_write_reg(opp80->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value);
}
curve = params->arr_curve_points;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_0_1,
REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_0_1,
REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_0_1,
REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_0_1,
REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS);
dm_write_reg(
opp80->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_0_1),
value);
}
curve += 2;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_2_3,
REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_2_3,
REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_2_3,
REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_2_3,
REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS);
dm_write_reg(opp80->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_2_3),
value);
}
curve += 2;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_4_5,
REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_4_5,
REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_4_5,
REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_4_5,
REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS);
dm_write_reg(opp80->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_4_5),
value);
}
curve += 2;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_6_7,
REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_6_7,
REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_6_7,
REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_6_7,
REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS);
dm_write_reg(opp80->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_6_7),
value);
}
curve += 2;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_8_9,
REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_8_9,
REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_8_9,
REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_8_9,
REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS);
dm_write_reg(opp80->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_8_9),
value);
}
curve += 2;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_10_11,
REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_10_11,
REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_10_11,
REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_10_11,
REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS);
dm_write_reg(opp80->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_10_11),
value);
}
curve += 2;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_12_13,
REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_12_13,
REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_12_13,
REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_12_13,
REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS);
dm_write_reg(opp80->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_12_13),
value);
}
curve += 2;
{
value = 0;
set_reg_field_value(
value,
curve[0].offset,
REGAMMA_CNTLA_REGION_14_15,
REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET);
set_reg_field_value(
value,
curve[0].segments_num,
REGAMMA_CNTLA_REGION_14_15,
REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS);
set_reg_field_value(
value,
curve[1].offset,
REGAMMA_CNTLA_REGION_14_15,
REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET);
set_reg_field_value(
value,
curve[1].segments_num,
REGAMMA_CNTLA_REGION_14_15,
REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS);
dm_write_reg(opp80->base.ctx,
DCP_REG(mmREGAMMA_CNTLA_REGION_14_15),
value);
}
}
static void program_pwl(
struct dce80_opp *opp80,
const struct pwl_params *params)
{
uint32_t value;
{
uint8_t max_tries = 10;
uint8_t counter = 0;
/* Power on LUT memory */
value = dm_read_reg(opp80->base.ctx,
DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL));
set_reg_field_value(
value,
1,
DCFE_MEM_LIGHT_SLEEP_CNTL,
REGAMMA_LUT_LIGHT_SLEEP_DIS);
dm_write_reg(opp80->base.ctx,
DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), value);
while (counter < max_tries) {
value =
dm_read_reg(
opp80->base.ctx,
DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL));
if (get_reg_field_value(
value,
DCFE_MEM_LIGHT_SLEEP_CNTL,
REGAMMA_LUT_MEM_PWR_STATE) == 0)
break;
++counter;
}
if (counter == max_tries) {
dm_logger_write(opp80->base.ctx->logger, LOG_WARNING,
"%s: regamma lut was not powered on "
"in a timely manner,"
" programming still proceeds\n",
__func__);
}
}
value = 0;
set_reg_field_value(
value,
7,
REGAMMA_LUT_WRITE_EN_MASK,
REGAMMA_LUT_WRITE_EN_MASK);
dm_write_reg(opp80->base.ctx,
DCP_REG(mmREGAMMA_LUT_WRITE_EN_MASK), value);
dm_write_reg(opp80->base.ctx,
DCP_REG(mmREGAMMA_LUT_INDEX), 0);
/* Program REGAMMA_LUT_DATA */
{
const uint32_t addr = DCP_REG(mmREGAMMA_LUT_DATA);
uint32_t i = 0;
const struct pwl_result_data *rgb =
params->rgb_resulted;
while (i != params->hw_points_num) {
dm_write_reg(opp80->base.ctx, addr, rgb->red_reg);
dm_write_reg(opp80->base.ctx, addr, rgb->green_reg);
dm_write_reg(opp80->base.ctx, addr, rgb->blue_reg);
dm_write_reg(opp80->base.ctx, addr,
rgb->delta_red_reg);
dm_write_reg(opp80->base.ctx, addr,
rgb->delta_green_reg);
dm_write_reg(opp80->base.ctx, addr,
rgb->delta_blue_reg);
++rgb;
++i;
}
}
/* we are done with DCP LUT memory; re-enable low power mode */
value = dm_read_reg(opp80->base.ctx,
DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL));
set_reg_field_value(
value,
0,
DCFE_MEM_LIGHT_SLEEP_CNTL,
REGAMMA_LUT_LIGHT_SLEEP_DIS);
dm_write_reg(opp80->base.ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL),
value);
}
void dce80_opp_power_on_regamma_lut(
struct output_pixel_processor *opp,
bool power_on)
{
struct dce80_opp *opp80 = TO_DCE80_OPP(opp);
uint32_t value =
dm_read_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL));
set_reg_field_value(
value,
power_on,
DCFE_MEM_LIGHT_SLEEP_CNTL,
REGAMMA_LUT_LIGHT_SLEEP_DIS);
set_reg_field_value(
value,
power_on,
DCFE_MEM_LIGHT_SLEEP_CNTL,
DCP_LUT_LIGHT_SLEEP_DIS);
dm_write_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), value);
}
bool dce80_opp_program_regamma_pwl(
struct output_pixel_processor *opp,
const struct pwl_params *params)
{
struct dce80_opp *opp80 = TO_DCE80_OPP(opp);
regamma_config_regions_and_segments(opp80, params);
program_pwl(opp80, params);
return true;
}
void dce80_opp_set_regamma_mode(struct output_pixel_processor *opp,
enum opp_regamma mode)
{
struct dce80_opp *opp80 = TO_DCE80_OPP(opp);
uint32_t value = dm_read_reg(opp80->base.ctx,
DCP_REG(mmREGAMMA_CONTROL));
set_reg_field_value(
value,
mode,
REGAMMA_CONTROL,
GRPH_REGAMMA_MODE);
dm_write_reg(opp80->base.ctx, DCP_REG(mmREGAMMA_CONTROL), value);
}
......@@ -43,7 +43,7 @@
#include "dce80/dce80_mem_input.h"
#include "dce80/dce80_ipp.h"
#include "dce/dce_transform.h"
#include "dce80/dce80_opp.h"
#include "dce/dce_opp.h"
#include "dce110/dce110_ipp.h"
#include "dce/dce_clocks.h"
#include "dce/dce_clock_source.h"
......@@ -317,6 +317,28 @@ static const struct dce_stream_encoder_mask se_mask = {
SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK)
};
#define opp_regs(id)\
[id] = {\
OPP_DCE_80_REG_LIST(id),\
}
static const struct dce_opp_registers opp_regs[] = {
opp_regs(0),
opp_regs(1),
opp_regs(2),
opp_regs(3),
opp_regs(4),
opp_regs(5)
};
static const struct dce_opp_shift opp_shift = {
OPP_COMMON_MASK_SH_LIST_DCE_80(__SHIFT)
};
static const struct dce_opp_mask opp_mask = {
OPP_COMMON_MASK_SH_LIST_DCE_80(_MASK)
};
#define audio_regs(id)\
[id] = {\
AUD_COMMON_REG_LIST(id)\
......@@ -419,6 +441,25 @@ static struct timing_generator *dce80_timing_generator_create(
return NULL;
}
static struct output_pixel_processor *dce80_opp_create(
struct dc_context *ctx,
uint32_t inst)
{
struct dce110_opp *opp =
dm_alloc(sizeof(struct dce110_opp));
if (!opp)
return NULL;
if (dce110_opp_construct(opp,
ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask))
return &opp->base;
BREAK_TO_DEBUGGER();
dm_free(opp);
return NULL;
}
static struct stream_encoder *dce80_stream_encoder_create(
enum engine_id eng_id,
struct dc_context *ctx)
......@@ -631,7 +672,7 @@ static void destruct(struct dce110_resource_pool *pool)
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.opps[i] != NULL)
dce80_opp_destroy(&pool->base.opps[i]);
dce110_opp_destroy(&pool->base.opps[i]);
if (pool->base.transforms[i] != NULL)
dce80_transform_destroy(&pool->base.transforms[i]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment