diff options
author | Leo (Sunpeng) Li <sunpeng.li@amd.com> | 2017-05-16 16:07:30 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2017-09-26 18:07:19 -0400 |
commit | 5aff86c1b3259f1443e0b35b74eb6dfd5b35791b (patch) | |
tree | 1953f025f213dcee082fc283064aee7c8542ccec /drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | |
parent | 98489c026edc48d9c783f783cc82f2e8811e0ee4 (diff) |
drm/amd/display: Implement input gamma LUT
1. Implemented dcn10_ipp_program_input_lut(), following the existing
interface.
2. Added missing registers as needed
3. Change to REG_GET for *ram_select() funcs.
4. Removed gamma table init from DiagsDM::make_surface() for resolving
CRC errors. Reason: Legacy LUT will be deprecated soon for Raven in
favor of degamma/regamma.
Signed-off-by: Leo (Sunpeng) Li <sunpeng.li@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 82 |
1 files changed, 81 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 082c98c11293..1e7a55d9e9ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -814,7 +814,9 @@ static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp, uint32_t status_reg = 0; struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - status_reg = (REG_READ(CM_IGAM_LUT_RW_CONTROL) & 0x0F00) >>16; + REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, + &status_reg); + if (status_reg == 9) { *ram_a_inuse = true; ret = true; @@ -825,6 +827,28 @@ static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp, return ret; } +static bool dcn10_ingamma_ram_inuse(struct input_pixel_processor *ipp, + bool *ram_a_inuse) +{ + bool in_use = false; + uint32_t status_reg = 0; + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, + &status_reg); + + // 1 => IGAM_RAMA, 3 => IGAM_RAMA & DGAM_ROMA, 4 => IGAM_RAMA & DGAM_ROMB + if (status_reg == 1 || status_reg == 3 || status_reg == 4) { + *ram_a_inuse = true; + in_use = true; + // 2 => IGAM_RAMB, 5 => IGAM_RAMB & DGAM_ROMA, 6 => IGAM_RAMB & DGAM_ROMB + } else if (status_reg == 2 || status_reg == 5 || status_reg == 6) { + *ram_a_inuse = false; + in_use = true; + } + return in_use; +} + static void dcn10_degamma_ram_select(struct input_pixel_processor *ipp, bool use_ram_a) { @@ -855,6 +879,61 @@ static void dcn10_ipp_set_degamma_pwl(struct input_pixel_processor *ipp, dcn10_degamma_ram_select(ipp, !is_ram_a); } +/* + * Input gamma LUT currently supports 256 values only. This means input color + * can have a maximum of 8 bits per channel (= 256 possible values) in order to + * have a one-to-one mapping with the LUT. Truncation will occur with color + * values greater than 8 bits. + * + * In the future, this function should support additional input gamma methods, + * such as piecewise linear mapping, and input gamma bypass. + */ +void dcn10_ipp_program_input_lut( + struct input_pixel_processor *ipp, + const struct dc_gamma *gamma) +{ + int i; + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + bool rama_occupied = false; + uint32_t ram_num; + // Power on LUT memory. + REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1); + dcn10_ipp_enable_cm_block(ipp); + // Determine whether to use RAM A or RAM B + dcn10_ingamma_ram_inuse(ipp, &rama_occupied); + if (!rama_occupied) + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0); + else + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 1); + // RW mode is 256-entry LUT + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, 0); + // IGAM Input format should be 8 bits per channel. + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 0); + // Do not mask any R,G,B values + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, 7); + // LUT-256, unsigned, integer, new u0.12 format + REG_UPDATE_3( + CM_IGAM_CONTROL, + CM_IGAM_LUT_FORMAT_R, 3, + CM_IGAM_LUT_FORMAT_G, 3, + CM_IGAM_LUT_FORMAT_B, 3); + // Start at index 0 of IGAM LUT + REG_UPDATE(CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, 0); + for (i = 0; i < INPUT_LUT_ENTRIES; i++) { + REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, + gamma->red[i]); + REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, + gamma->green[i]); + REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, + gamma->blue[i]); + } + // Power off LUT memory + REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 0); + // Enable IGAM LUT on ram we just wrote to. 2 => RAMA, 3 => RAMB + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, rama_occupied ? 3 : 2); + REG_GET(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, &ram_num); +} + /*****************************************/ /* Constructor, Destructor */ /*****************************************/ @@ -869,6 +948,7 @@ static const struct ipp_funcs dcn10_ipp_funcs = { .ipp_cursor_set_attributes = dcn10_cursor_set_attributes, .ipp_cursor_set_position = dcn10_cursor_set_position, .ipp_set_degamma = dcn10_ipp_set_degamma, + .ipp_program_input_lut = dcn10_ipp_program_input_lut, .ipp_full_bypass = dcn10_ipp_full_bypass, .ipp_setup = dcn10_ipp_cnv_setup, .ipp_program_degamma_pwl = dcn10_ipp_set_degamma_pwl, |