diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c new file mode 100644 index 000000000000..2d9072138834 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c @@ -0,0 +1,215 @@ +/* + * 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; +} |