/*
|
* 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 <linux/delay.h>
|
|
#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_transform_v.h"
|
|
static void power_on_lut(struct transform *xfm,
|
bool power_on, bool inputgamma, bool regamma)
|
{
|
uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL);
|
int i;
|
|
if (power_on) {
|
if (inputgamma)
|
set_reg_field_value(
|
value,
|
1,
|
DCFEV_MEM_PWR_CTRL,
|
COL_MAN_INPUT_GAMMA_MEM_PWR_DIS);
|
if (regamma)
|
set_reg_field_value(
|
value,
|
1,
|
DCFEV_MEM_PWR_CTRL,
|
COL_MAN_GAMMA_CORR_MEM_PWR_DIS);
|
} else {
|
if (inputgamma)
|
set_reg_field_value(
|
value,
|
0,
|
DCFEV_MEM_PWR_CTRL,
|
COL_MAN_INPUT_GAMMA_MEM_PWR_DIS);
|
if (regamma)
|
set_reg_field_value(
|
value,
|
0,
|
DCFEV_MEM_PWR_CTRL,
|
COL_MAN_GAMMA_CORR_MEM_PWR_DIS);
|
}
|
|
dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value);
|
|
for (i = 0; i < 3; i++) {
|
value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL);
|
if (get_reg_field_value(value,
|
DCFEV_MEM_PWR_CTRL,
|
COL_MAN_INPUT_GAMMA_MEM_PWR_DIS) &&
|
get_reg_field_value(value,
|
DCFEV_MEM_PWR_CTRL,
|
COL_MAN_GAMMA_CORR_MEM_PWR_DIS))
|
break;
|
|
udelay(2);
|
}
|
}
|
|
static void set_bypass_input_gamma(struct dce_transform *xfm_dce)
|
{
|
uint32_t value;
|
|
value = dm_read_reg(xfm_dce->base.ctx,
|
mmCOL_MAN_INPUT_GAMMA_CONTROL1);
|
|
set_reg_field_value(
|
value,
|
0,
|
COL_MAN_INPUT_GAMMA_CONTROL1,
|
INPUT_GAMMA_MODE);
|
|
dm_write_reg(xfm_dce->base.ctx,
|
mmCOL_MAN_INPUT_GAMMA_CONTROL1, value);
|
}
|
|
static void configure_regamma_mode(struct dce_transform *xfm_dce, uint32_t mode)
|
{
|
uint32_t value = 0;
|
|
set_reg_field_value(
|
value,
|
mode,
|
GAMMA_CORR_CONTROL,
|
GAMMA_CORR_MODE);
|
|
dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CONTROL, 0);
|
}
|
|
/*
|
*****************************************************************************
|
* 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 dce_transform *xfm_dce, 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,
|
GAMMA_CORR_CNTLA_START_CNTL,
|
GAMMA_CORR_CNTLA_EXP_REGION_START);
|
|
set_reg_field_value(
|
value,
|
0,
|
GAMMA_CORR_CNTLA_START_CNTL,
|
GAMMA_CORR_CNTLA_EXP_REGION_START_SEGMENT);
|
|
dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_START_CNTL,
|
value);
|
}
|
{
|
value = 0;
|
set_reg_field_value(
|
value,
|
params->arr_points[0].custom_float_slope,
|
GAMMA_CORR_CNTLA_SLOPE_CNTL,
|
GAMMA_CORR_CNTLA_EXP_REGION_LINEAR_SLOPE);
|
|
dm_write_reg(xfm_dce->base.ctx,
|
mmGAMMA_CORR_CNTLA_SLOPE_CNTL, value);
|
}
|
{
|
value = 0;
|
set_reg_field_value(
|
value,
|
params->arr_points[1].custom_float_x,
|
GAMMA_CORR_CNTLA_END_CNTL1,
|
GAMMA_CORR_CNTLA_EXP_REGION_END);
|
|
dm_write_reg(xfm_dce->base.ctx,
|
mmGAMMA_CORR_CNTLA_END_CNTL1, value);
|
}
|
{
|
value = 0;
|
set_reg_field_value(
|
value,
|
params->arr_points[1].custom_float_slope,
|
GAMMA_CORR_CNTLA_END_CNTL2,
|
GAMMA_CORR_CNTLA_EXP_REGION_END_BASE);
|
|
set_reg_field_value(
|
value,
|
params->arr_points[1].custom_float_y,
|
GAMMA_CORR_CNTLA_END_CNTL2,
|
GAMMA_CORR_CNTLA_EXP_REGION_END_SLOPE);
|
|
dm_write_reg(xfm_dce->base.ctx,
|
mmGAMMA_CORR_CNTLA_END_CNTL2, value);
|
}
|
|
curve = params->arr_curve_points;
|
|
{
|
value = 0;
|
set_reg_field_value(
|
value,
|
curve[0].offset,
|
GAMMA_CORR_CNTLA_REGION_0_1,
|
GAMMA_CORR_CNTLA_EXP_REGION0_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[0].segments_num,
|
GAMMA_CORR_CNTLA_REGION_0_1,
|
GAMMA_CORR_CNTLA_EXP_REGION0_NUM_SEGMENTS);
|
|
set_reg_field_value(
|
value,
|
curve[1].offset,
|
GAMMA_CORR_CNTLA_REGION_0_1,
|
GAMMA_CORR_CNTLA_EXP_REGION1_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[1].segments_num,
|
GAMMA_CORR_CNTLA_REGION_0_1,
|
GAMMA_CORR_CNTLA_EXP_REGION1_NUM_SEGMENTS);
|
|
dm_write_reg(
|
xfm_dce->base.ctx,
|
mmGAMMA_CORR_CNTLA_REGION_0_1,
|
value);
|
}
|
|
curve += 2;
|
{
|
value = 0;
|
set_reg_field_value(
|
value,
|
curve[0].offset,
|
GAMMA_CORR_CNTLA_REGION_2_3,
|
GAMMA_CORR_CNTLA_EXP_REGION2_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[0].segments_num,
|
GAMMA_CORR_CNTLA_REGION_2_3,
|
GAMMA_CORR_CNTLA_EXP_REGION2_NUM_SEGMENTS);
|
|
set_reg_field_value(
|
value,
|
curve[1].offset,
|
GAMMA_CORR_CNTLA_REGION_2_3,
|
GAMMA_CORR_CNTLA_EXP_REGION3_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[1].segments_num,
|
GAMMA_CORR_CNTLA_REGION_2_3,
|
GAMMA_CORR_CNTLA_EXP_REGION3_NUM_SEGMENTS);
|
|
dm_write_reg(xfm_dce->base.ctx,
|
mmGAMMA_CORR_CNTLA_REGION_2_3,
|
value);
|
}
|
|
curve += 2;
|
{
|
value = 0;
|
set_reg_field_value(
|
value,
|
curve[0].offset,
|
GAMMA_CORR_CNTLA_REGION_4_5,
|
GAMMA_CORR_CNTLA_EXP_REGION4_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[0].segments_num,
|
GAMMA_CORR_CNTLA_REGION_4_5,
|
GAMMA_CORR_CNTLA_EXP_REGION4_NUM_SEGMENTS);
|
|
set_reg_field_value(
|
value,
|
curve[1].offset,
|
GAMMA_CORR_CNTLA_REGION_4_5,
|
GAMMA_CORR_CNTLA_EXP_REGION5_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[1].segments_num,
|
GAMMA_CORR_CNTLA_REGION_4_5,
|
GAMMA_CORR_CNTLA_EXP_REGION5_NUM_SEGMENTS);
|
|
dm_write_reg(xfm_dce->base.ctx,
|
mmGAMMA_CORR_CNTLA_REGION_4_5,
|
value);
|
}
|
|
curve += 2;
|
{
|
value = 0;
|
set_reg_field_value(
|
value,
|
curve[0].offset,
|
GAMMA_CORR_CNTLA_REGION_6_7,
|
GAMMA_CORR_CNTLA_EXP_REGION6_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[0].segments_num,
|
GAMMA_CORR_CNTLA_REGION_6_7,
|
GAMMA_CORR_CNTLA_EXP_REGION6_NUM_SEGMENTS);
|
|
set_reg_field_value(
|
value,
|
curve[1].offset,
|
GAMMA_CORR_CNTLA_REGION_6_7,
|
GAMMA_CORR_CNTLA_EXP_REGION7_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[1].segments_num,
|
GAMMA_CORR_CNTLA_REGION_6_7,
|
GAMMA_CORR_CNTLA_EXP_REGION7_NUM_SEGMENTS);
|
|
dm_write_reg(xfm_dce->base.ctx,
|
mmGAMMA_CORR_CNTLA_REGION_6_7,
|
value);
|
}
|
|
curve += 2;
|
{
|
value = 0;
|
set_reg_field_value(
|
value,
|
curve[0].offset,
|
GAMMA_CORR_CNTLA_REGION_8_9,
|
GAMMA_CORR_CNTLA_EXP_REGION8_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[0].segments_num,
|
GAMMA_CORR_CNTLA_REGION_8_9,
|
GAMMA_CORR_CNTLA_EXP_REGION8_NUM_SEGMENTS);
|
|
set_reg_field_value(
|
value,
|
curve[1].offset,
|
GAMMA_CORR_CNTLA_REGION_8_9,
|
GAMMA_CORR_CNTLA_EXP_REGION9_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[1].segments_num,
|
GAMMA_CORR_CNTLA_REGION_8_9,
|
GAMMA_CORR_CNTLA_EXP_REGION9_NUM_SEGMENTS);
|
|
dm_write_reg(xfm_dce->base.ctx,
|
mmGAMMA_CORR_CNTLA_REGION_8_9,
|
value);
|
}
|
|
curve += 2;
|
{
|
value = 0;
|
set_reg_field_value(
|
value,
|
curve[0].offset,
|
GAMMA_CORR_CNTLA_REGION_10_11,
|
GAMMA_CORR_CNTLA_EXP_REGION10_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[0].segments_num,
|
GAMMA_CORR_CNTLA_REGION_10_11,
|
GAMMA_CORR_CNTLA_EXP_REGION10_NUM_SEGMENTS);
|
|
set_reg_field_value(
|
value,
|
curve[1].offset,
|
GAMMA_CORR_CNTLA_REGION_10_11,
|
GAMMA_CORR_CNTLA_EXP_REGION11_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[1].segments_num,
|
GAMMA_CORR_CNTLA_REGION_10_11,
|
GAMMA_CORR_CNTLA_EXP_REGION11_NUM_SEGMENTS);
|
|
dm_write_reg(xfm_dce->base.ctx,
|
mmGAMMA_CORR_CNTLA_REGION_10_11,
|
value);
|
}
|
|
curve += 2;
|
{
|
value = 0;
|
set_reg_field_value(
|
value,
|
curve[0].offset,
|
GAMMA_CORR_CNTLA_REGION_12_13,
|
GAMMA_CORR_CNTLA_EXP_REGION12_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[0].segments_num,
|
GAMMA_CORR_CNTLA_REGION_12_13,
|
GAMMA_CORR_CNTLA_EXP_REGION12_NUM_SEGMENTS);
|
|
set_reg_field_value(
|
value,
|
curve[1].offset,
|
GAMMA_CORR_CNTLA_REGION_12_13,
|
GAMMA_CORR_CNTLA_EXP_REGION13_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[1].segments_num,
|
GAMMA_CORR_CNTLA_REGION_12_13,
|
GAMMA_CORR_CNTLA_EXP_REGION13_NUM_SEGMENTS);
|
|
dm_write_reg(xfm_dce->base.ctx,
|
mmGAMMA_CORR_CNTLA_REGION_12_13,
|
value);
|
}
|
|
curve += 2;
|
{
|
value = 0;
|
set_reg_field_value(
|
value,
|
curve[0].offset,
|
GAMMA_CORR_CNTLA_REGION_14_15,
|
GAMMA_CORR_CNTLA_EXP_REGION14_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[0].segments_num,
|
GAMMA_CORR_CNTLA_REGION_14_15,
|
GAMMA_CORR_CNTLA_EXP_REGION14_NUM_SEGMENTS);
|
|
set_reg_field_value(
|
value,
|
curve[1].offset,
|
GAMMA_CORR_CNTLA_REGION_14_15,
|
GAMMA_CORR_CNTLA_EXP_REGION15_LUT_OFFSET);
|
|
set_reg_field_value(
|
value,
|
curve[1].segments_num,
|
GAMMA_CORR_CNTLA_REGION_14_15,
|
GAMMA_CORR_CNTLA_EXP_REGION15_NUM_SEGMENTS);
|
|
dm_write_reg(xfm_dce->base.ctx,
|
mmGAMMA_CORR_CNTLA_REGION_14_15,
|
value);
|
}
|
}
|
|
static void program_pwl(struct dce_transform *xfm_dce,
|
const struct pwl_params *params)
|
{
|
uint32_t value = 0;
|
|
set_reg_field_value(
|
value,
|
7,
|
GAMMA_CORR_LUT_WRITE_EN_MASK,
|
GAMMA_CORR_LUT_WRITE_EN_MASK);
|
|
dm_write_reg(xfm_dce->base.ctx,
|
mmGAMMA_CORR_LUT_WRITE_EN_MASK, value);
|
|
dm_write_reg(xfm_dce->base.ctx,
|
mmGAMMA_CORR_LUT_INDEX, 0);
|
|
/* Program REGAMMA_LUT_DATA */
|
{
|
const uint32_t addr = mmGAMMA_CORR_LUT_DATA;
|
uint32_t i = 0;
|
const struct pwl_result_data *rgb =
|
params->rgb_resulted;
|
|
while (i != params->hw_points_num) {
|
dm_write_reg(xfm_dce->base.ctx, addr, rgb->red_reg);
|
dm_write_reg(xfm_dce->base.ctx, addr, rgb->green_reg);
|
dm_write_reg(xfm_dce->base.ctx, addr, rgb->blue_reg);
|
|
dm_write_reg(xfm_dce->base.ctx, addr,
|
rgb->delta_red_reg);
|
dm_write_reg(xfm_dce->base.ctx, addr,
|
rgb->delta_green_reg);
|
dm_write_reg(xfm_dce->base.ctx, addr,
|
rgb->delta_blue_reg);
|
|
++rgb;
|
++i;
|
}
|
}
|
}
|
|
void dce110_opp_program_regamma_pwl_v(
|
struct transform *xfm,
|
const struct pwl_params *params)
|
{
|
struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
|
|
/* Setup regions */
|
regamma_config_regions_and_segments(xfm_dce, params);
|
|
set_bypass_input_gamma(xfm_dce);
|
|
/* Power on gamma LUT memory */
|
power_on_lut(xfm, true, false, true);
|
|
/* Program PWL */
|
program_pwl(xfm_dce, params);
|
|
/* program regamma config */
|
configure_regamma_mode(xfm_dce, 1);
|
|
/* Power return to auto back */
|
power_on_lut(xfm, false, false, true);
|
}
|
|
void dce110_opp_power_on_regamma_lut_v(
|
struct transform *xfm,
|
bool power_on)
|
{
|
uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL);
|
|
set_reg_field_value(
|
value,
|
0,
|
DCFEV_MEM_PWR_CTRL,
|
COL_MAN_GAMMA_CORR_MEM_PWR_FORCE);
|
|
set_reg_field_value(
|
value,
|
power_on,
|
DCFEV_MEM_PWR_CTRL,
|
COL_MAN_GAMMA_CORR_MEM_PWR_DIS);
|
|
set_reg_field_value(
|
value,
|
0,
|
DCFEV_MEM_PWR_CTRL,
|
COL_MAN_INPUT_GAMMA_MEM_PWR_FORCE);
|
|
set_reg_field_value(
|
value,
|
power_on,
|
DCFEV_MEM_PWR_CTRL,
|
COL_MAN_INPUT_GAMMA_MEM_PWR_DIS);
|
|
dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value);
|
}
|
|
void dce110_opp_set_regamma_mode_v(
|
struct transform *xfm,
|
enum opp_regamma mode)
|
{
|
// TODO: need to implement the function
|
}
|