1132718Skan/* $NetBSD: amdgpu_dce_opp.c,v 1.2 2021/12/18 23:45:02 riastradh Exp $ */ 272562Sobrien 3169689Skan/* 4169689Skan * Copyright 2012-15 Advanced Micro Devices, Inc. 550397Sobrien * 6132718Skan * Permission is hereby granted, free of charge, to any person obtaining a 750397Sobrien * copy of this software and associated documentation files (the "Software"), 850397Sobrien * to deal in the Software without restriction, including without limitation 9132718Skan * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1050397Sobrien * and/or sell copies of the Software, and to permit persons to whom the 11132718Skan * Software is furnished to do so, subject to the following conditions: 1250397Sobrien * 1350397Sobrien * The above copyright notice and this permission notice shall be included in 1450397Sobrien * all copies or substantial portions of the Software. 1550397Sobrien * 16132718Skan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1750397Sobrien * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1850397Sobrien * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1950397Sobrien * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 2050397Sobrien * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2150397Sobrien * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22132718Skan * OTHER DEALINGS IN THE SOFTWARE. 23169689Skan * 24169689Skan * Authors: AMD 2550397Sobrien * 2650397Sobrien */ 2750397Sobrien 28132718Skan#include <sys/cdefs.h> 29132718Skan__KERNEL_RCSID(0, "$NetBSD: amdgpu_dce_opp.c,v 1.2 2021/12/18 23:45:02 riastradh Exp $"); 3050397Sobrien 3150397Sobrien#include <linux/slab.h> 3250397Sobrien 3350397Sobrien#include "dm_services.h" 3450397Sobrien#include "basics/conversion.h" 3550397Sobrien 36169689Skan#include "dce_opp.h" 3750397Sobrien 3850397Sobrien#include "reg_helper.h" 3950397Sobrien 4050397Sobrien#define REG(reg)\ 4190075Sobrien (opp110->regs->reg) 4250397Sobrien 4390075Sobrien#undef FN 4450397Sobrien#define FN(reg_name, field_name) \ 4550397Sobrien opp110->opp_shift->field_name, opp110->opp_mask->field_name 4690075Sobrien 4790075Sobrien#define CTX \ 4890075Sobrien opp110->base.ctx 4990075Sobrien 5090075Sobrienenum { 51132718Skan MAX_PWL_ENTRY = 128, 52169689Skan MAX_REGIONS_NUMBER = 16 53169689Skan}; 5450397Sobrien 55169689Skanenum { 56169689Skan MAX_LUT_ENTRY = 256, 57169689Skan MAX_NUMBER_OF_ENTRIES = 256 58169689Skan}; 59169689Skan 60169689Skan 61169689Skanenum { 62169689Skan OUTPUT_CSC_MATRIX_SIZE = 12 63169689Skan}; 64169689Skan 65169689Skan 66169689Skan 67169689Skan 68169689Skan 69169689Skan 70169689Skan 71169689Skan 72169689Skan 73169689Skan 74169689Skan 75169689Skan 76169689Skan 77169689Skan 78169689Skan 7950397Sobrien 80169689Skan 81169689Skan 82169689Skan 83169689Skan 84169689Skan 85169689Skan 86169689Skan/* 87169689Skan ***************************************************************************** 88169689Skan * Function: regamma_config_regions_and_segments 89169689Skan * 90169689Skan * build regamma curve by using predefined hw points 91169689Skan * uses interface parameters ,like EDID coeff. 92169689Skan * 93169689Skan * @param : parameters interface parameters 94169689Skan * @return void 95169689Skan * 96169689Skan * @note 97169689Skan * 98169689Skan * @see 99169689Skan * 100169689Skan ***************************************************************************** 101169689Skan */ 102169689Skan 10350397Sobrien 104169689Skan 105169689Skan/** 106169689Skan * set_truncation 107169689Skan * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp 108169689Skan * 2) enable truncation 109169689Skan * 3) HW remove 12bit FMT support for DCE11 power saving reason. 110169689Skan */ 111169689Skanstatic void set_truncation( 112169689Skan struct dce110_opp *opp110, 113169689Skan const struct bit_depth_reduction_params *params) 114169689Skan{ 115169689Skan /*Disable truncation*/ 116169689Skan REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 117169689Skan FMT_TRUNCATE_EN, 0, 118169689Skan FMT_TRUNCATE_DEPTH, 0, 119169689Skan FMT_TRUNCATE_MODE, 0); 120169689Skan 121169689Skan 122169689Skan if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { 123169689Skan /* 8bpc trunc on YCbCr422*/ 124169689Skan if (params->flags.TRUNCATE_DEPTH == 1) 125169689Skan REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 126169689Skan FMT_TRUNCATE_EN, 1, 127169689Skan FMT_TRUNCATE_DEPTH, 1, 128169689Skan FMT_TRUNCATE_MODE, 0); 129169689Skan else if (params->flags.TRUNCATE_DEPTH == 2) 130169689Skan /* 10bpc trunc on YCbCr422*/ 131169689Skan REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 132169689Skan FMT_TRUNCATE_EN, 1, 133169689Skan FMT_TRUNCATE_DEPTH, 2, 134169689Skan FMT_TRUNCATE_MODE, 0); 135169689Skan return; 136169689Skan } 137169689Skan /* on other format-to do */ 138169689Skan if (params->flags.TRUNCATE_ENABLED == 0) 139169689Skan return; 140169689Skan /*Set truncation depth and Enable truncation*/ 141169689Skan REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 142169689Skan FMT_TRUNCATE_EN, 1, 143169689Skan FMT_TRUNCATE_DEPTH, 144169689Skan params->flags.TRUNCATE_DEPTH, 145169689Skan FMT_TRUNCATE_MODE, 146169689Skan params->flags.TRUNCATE_MODE); 147169689Skan} 148169689Skan 149169689Skan 150169689Skan/** 151169689Skan * set_spatial_dither 152169689Skan * 1) set spatial dithering mode: pattern of seed 153169689Skan * 2) set spatial dithering depth: 0 for 18bpp or 1 for 24bpp 154169689Skan * 3) set random seed 155169689Skan * 4) set random mode 156169689Skan * lfsr is reset every frame or not reset 157169689Skan * RGB dithering method 158169689Skan * 0: RGB data are all dithered with x^28+x^3+1 159169689Skan * 1: R data is dithered with x^28+x^3+1 160169689Skan * G data is dithered with x^28+X^9+1 161169689Skan * B data is dithered with x^28+x^13+1 162169689Skan * enable high pass filter or not 163169689Skan * 5) enable spatical dithering 164169689Skan */ 165169689Skanstatic void set_spatial_dither( 166169689Skan struct dce110_opp *opp110, 167169689Skan const struct bit_depth_reduction_params *params) 168169689Skan{ 169169689Skan /*Disable spatial (random) dithering*/ 170169689Skan REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 171169689Skan FMT_SPATIAL_DITHER_EN, 0, 172169689Skan FMT_SPATIAL_DITHER_DEPTH, 0, 173169689Skan FMT_SPATIAL_DITHER_MODE, 0); 174169689Skan 175169689Skan REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 176169689Skan FMT_HIGHPASS_RANDOM_ENABLE, 0, 177169689Skan FMT_FRAME_RANDOM_ENABLE, 0, 178169689Skan FMT_RGB_RANDOM_ENABLE, 0); 179169689Skan 180169689Skan REG_UPDATE(FMT_BIT_DEPTH_CONTROL, 181169689Skan FMT_TEMPORAL_DITHER_EN, 0); 182169689Skan 183169689Skan /* no 10bpc on DCE11*/ 184169689Skan if (params->flags.SPATIAL_DITHER_ENABLED == 0 || 185169689Skan params->flags.SPATIAL_DITHER_DEPTH == 2) 186169689Skan return; 187169689Skan 188169689Skan /* only use FRAME_COUNTER_MAX if frameRandom == 1*/ 189169689Skan 190169689Skan if (opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX && 191169689Skan opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP) { 192169689Skan if (params->flags.FRAME_RANDOM == 1) { 193169689Skan if (params->flags.SPATIAL_DITHER_DEPTH == 0 || 194169689Skan params->flags.SPATIAL_DITHER_DEPTH == 1) { 195169689Skan REG_UPDATE_2(FMT_CONTROL, 196169689Skan FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15, 197169689Skan FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2); 198169689Skan } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) { 199169689Skan REG_UPDATE_2(FMT_CONTROL, 200169689Skan FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3, 201169689Skan FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1); 202169689Skan } else 203169689Skan return; 204169689Skan } else { 205169689Skan REG_UPDATE_2(FMT_CONTROL, 206169689Skan FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0, 207169689Skan FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0); 208169689Skan } 209169689Skan } 210169689Skan /* Set seed for random values for 211169689Skan * spatial dithering for R,G,B channels 212169689Skan */ 213169689Skan REG_UPDATE(FMT_DITHER_RAND_R_SEED, 214169689Skan FMT_RAND_R_SEED, params->r_seed_value); 215169689Skan 216169689Skan REG_UPDATE(FMT_DITHER_RAND_G_SEED, 217169689Skan FMT_RAND_G_SEED, params->g_seed_value); 218169689Skan 219169689Skan REG_UPDATE(FMT_DITHER_RAND_B_SEED, 220169689Skan FMT_RAND_B_SEED, params->b_seed_value); 221169689Skan 222169689Skan /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero 223169689Skan * offset for the R/Cr channel, lower 4LSB 224169689Skan * is forced to zeros. Typically set to 0 225169689Skan * RGB and 0x80000 YCbCr. 226169689Skan */ 227169689Skan /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero 228169689Skan * offset for the G/Y channel, lower 4LSB is 229169689Skan * forced to zeros. Typically set to 0 RGB 230169689Skan * and 0x80000 YCbCr. 231169689Skan */ 232169689Skan /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero 233169689Skan * offset for the B/Cb channel, lower 4LSB is 234169689Skan * forced to zeros. Typically set to 0 RGB and 235169689Skan * 0x80000 YCbCr. 236169689Skan */ 23750397Sobrien 23850397Sobrien /* Disable High pass filter 23950397Sobrien * Reset only at startup 240169689Skan * Set RGB data dithered with x^28+x^3+1 241169689Skan */ 242169689Skan REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 24350397Sobrien FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM, 24450397Sobrien FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM, 245132718Skan FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM); 246132718Skan 24750397Sobrien /* Set spatial dithering bit depth 24896263Sobrien * Set spatial dithering mode 24996263Sobrien * (default is Seed patterrn AAAA...) 25090075Sobrien * Enable spatial dithering 25190075Sobrien */ 252169689Skan REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 253169689Skan FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH, 254169689Skan FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE, 255169689Skan FMT_SPATIAL_DITHER_EN, 1); 256169689Skan} 257169689Skan 25850397Sobrien/** 25950397Sobrien * SetTemporalDither (Frame Modulation) 260169689Skan * 1) set temporal dither depth 26150397Sobrien * 2) select pattern: from hard-coded pattern or programmable pattern 26296263Sobrien * 3) select optimized strips for BGR or RGB LCD sub-pixel 26396263Sobrien * 4) set s matrix 26496263Sobrien * 5) set t matrix 26596263Sobrien * 6) set grey level for 0.25, 0.5, 0.75 26650397Sobrien * 7) enable temporal dithering 26750397Sobrien */ 26850397Sobrien 26950397Sobrienstatic void set_temporal_dither( 27050397Sobrien struct dce110_opp *opp110, 27150397Sobrien const struct bit_depth_reduction_params *params) 27250397Sobrien{ 27350397Sobrien /*Disable temporal (frame modulation) dithering first*/ 27450397Sobrien REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 27550397Sobrien FMT_TEMPORAL_DITHER_EN, 0, 27650397Sobrien FMT_TEMPORAL_DITHER_RESET, 0, 27750397Sobrien FMT_TEMPORAL_DITHER_OFFSET, 0); 27850397Sobrien 27950397Sobrien REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL, 28050397Sobrien FMT_TEMPORAL_DITHER_DEPTH, 0, 28190075Sobrien FMT_TEMPORAL_LEVEL, 0); 28290075Sobrien 28390075Sobrien REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 28490075Sobrien FMT_25FRC_SEL, 0, 28590075Sobrien FMT_50FRC_SEL, 0, 28690075Sobrien FMT_75FRC_SEL, 0); 28790075Sobrien 28890075Sobrien /* no 10bpc dither on DCE11*/ 28990075Sobrien if (params->flags.FRAME_MODULATION_ENABLED == 0 || 29090075Sobrien params->flags.FRAME_MODULATION_DEPTH == 2) 29190075Sobrien return; 29290075Sobrien 29390075Sobrien /* Set temporal dithering depth*/ 29490075Sobrien REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 29590075Sobrien FMT_TEMPORAL_DITHER_DEPTH, params->flags.FRAME_MODULATION_DEPTH, 29690075Sobrien FMT_TEMPORAL_DITHER_RESET, 0, 29790075Sobrien FMT_TEMPORAL_DITHER_OFFSET, 0); 29890075Sobrien 299132718Skan /*Select legacy pattern based on FRC and Temporal level*/ 300132718Skan if (REG(FMT_TEMPORAL_DITHER_PATTERN_CONTROL)) { 301132718Skan REG_WRITE(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, 0); 302132718Skan /*Set s matrix*/ 303169689Skan REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, 0); 304169689Skan /*Set t matrix*/ 305169689Skan REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, 0); 306169689Skan } 307169689Skan 308169689Skan /*Select patterns for 0.25, 0.5 and 0.75 grey level*/ 309169689Skan REG_UPDATE(FMT_BIT_DEPTH_CONTROL, 310169689Skan FMT_TEMPORAL_LEVEL, params->flags.TEMPORAL_LEVEL); 311169689Skan 312132718Skan REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 313132718Skan FMT_25FRC_SEL, params->flags.FRC25, 314169689Skan FMT_50FRC_SEL, params->flags.FRC50, 315169689Skan FMT_75FRC_SEL, params->flags.FRC75); 31650397Sobrien 317169689Skan /*Enable bit reduction by temporal (frame modulation) dithering*/ 318169689Skan REG_UPDATE(FMT_BIT_DEPTH_CONTROL, 319169689Skan FMT_TEMPORAL_DITHER_EN, 1); 320169689Skan} 321169689Skan 322132718Skan/** 32350397Sobrien * Set Clamping 324169689Skan * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) 325169689Skan * 1 for 8 bpc 326169689Skan * 2 for 10 bpc 327169689Skan * 3 for 12 bpc 328132718Skan * 7 for programable 329132718Skan * 2) Enable clamp if Limited range requested 330132718Skan */ 331132718Skanvoid dce110_opp_set_clamping( 33250397Sobrien struct dce110_opp *opp110, 333132718Skan const struct clamping_and_pixel_encoding_params *params) 334132718Skan{ 33552284Sobrien REG_SET_2(FMT_CLAMP_CNTL, 0, 336132718Skan FMT_CLAMP_DATA_EN, 0, 337132718Skan FMT_CLAMP_COLOR_FORMAT, 0); 338132718Skan 339169689Skan switch (params->clamping_level) { 340132718Skan case CLAMPING_FULL_RANGE: 341132718Skan break; 342132718Skan case CLAMPING_LIMITED_RANGE_8BPC: 343169689Skan REG_SET_2(FMT_CLAMP_CNTL, 0, 344169689Skan FMT_CLAMP_DATA_EN, 1, 345169689Skan FMT_CLAMP_COLOR_FORMAT, 1); 346169689Skan break; 347169689Skan case CLAMPING_LIMITED_RANGE_10BPC: 348169689Skan REG_SET_2(FMT_CLAMP_CNTL, 0, 34990075Sobrien FMT_CLAMP_DATA_EN, 1, 350169689Skan FMT_CLAMP_COLOR_FORMAT, 2); 35190075Sobrien break; 35252284Sobrien case CLAMPING_LIMITED_RANGE_12BPC: 353132718Skan REG_SET_2(FMT_CLAMP_CNTL, 0, 354132718Skan FMT_CLAMP_DATA_EN, 1, 355132718Skan FMT_CLAMP_COLOR_FORMAT, 3); 356132718Skan break; 35796263Sobrien case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: 358132718Skan /*Set clamp control*/ 359132718Skan REG_SET_2(FMT_CLAMP_CNTL, 0, 360132718Skan FMT_CLAMP_DATA_EN, 1, 361132718Skan FMT_CLAMP_COLOR_FORMAT, 7); 362132718Skan 363117395Skan /*set the defaults*/ 364132718Skan REG_SET_2(FMT_CLAMP_COMPONENT_R, 0, 365132718Skan FMT_CLAMP_LOWER_R, 0x10, 366169689Skan FMT_CLAMP_UPPER_R, 0xFEF); 367169689Skan 368169689Skan REG_SET_2(FMT_CLAMP_COMPONENT_G, 0, 369169689Skan FMT_CLAMP_LOWER_G, 0x10, 370169689Skan FMT_CLAMP_UPPER_G, 0xFEF); 371169689Skan 372132718Skan REG_SET_2(FMT_CLAMP_COMPONENT_B, 0, 373132718Skan FMT_CLAMP_LOWER_B, 0x10, 374146895Skan FMT_CLAMP_UPPER_B, 0xFEF); 375146895Skan break; 376132718Skan default: 377132718Skan break; 378132718Skan } 379132718Skan} 380132718Skan 381132718Skan/** 382132718Skan * set_pixel_encoding 383169689Skan * 384169689Skan * Set Pixel Encoding 385169689Skan * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly 386169689Skan * 1: YCbCr 4:2:2 387169689Skan */ 388169689Skanstatic void set_pixel_encoding( 389169689Skan struct dce110_opp *opp110, 390169689Skan const struct clamping_and_pixel_encoding_params *params) 391169689Skan{ 392169689Skan if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS) 393169689Skan REG_UPDATE_3(FMT_CONTROL, 394169689Skan FMT_PIXEL_ENCODING, 0, 395169689Skan FMT_SUBSAMPLING_MODE, 0, 396169689Skan FMT_CBCR_BIT_REDUCTION_BYPASS, 0); 397169689Skan else 398169689Skan REG_UPDATE_2(FMT_CONTROL, 399169689Skan FMT_PIXEL_ENCODING, 0, 400169689Skan FMT_SUBSAMPLING_MODE, 0); 401169689Skan 40250397Sobrien if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { 40350397Sobrien REG_UPDATE_2(FMT_CONTROL, 40450397Sobrien FMT_PIXEL_ENCODING, 1, 40550397Sobrien FMT_SUBSAMPLING_ORDER, 0); 40650397Sobrien } 40750397Sobrien if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) { 40890075Sobrien REG_UPDATE_3(FMT_CONTROL, 40950397Sobrien FMT_PIXEL_ENCODING, 2, 41050397Sobrien FMT_SUBSAMPLING_MODE, 2, 41150397Sobrien FMT_CBCR_BIT_REDUCTION_BYPASS, 1); 41250397Sobrien } 41350397Sobrien 41450397Sobrien} 41550397Sobrien 41650397Sobrienvoid dce110_opp_program_bit_depth_reduction( 41750397Sobrien struct output_pixel_processor *opp, 41850397Sobrien const struct bit_depth_reduction_params *params) 41950397Sobrien{ 42050397Sobrien struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 421169689Skan 422169689Skan set_truncation(opp110, params); 423169689Skan set_spatial_dither(opp110, params); 424169689Skan set_temporal_dither(opp110, params); 42590075Sobrien} 42650397Sobrien 42790075Sobrienvoid dce110_opp_program_clamping_and_pixel_encoding( 42890075Sobrien struct output_pixel_processor *opp, 42990075Sobrien const struct clamping_and_pixel_encoding_params *params) 43090075Sobrien{ 43190075Sobrien struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 43290075Sobrien 43390075Sobrien dce110_opp_set_clamping(opp110, params); 43490075Sobrien set_pixel_encoding(opp110, params); 43590075Sobrien} 43690075Sobrien 43790075Sobrienstatic void program_formatter_420_memory(struct output_pixel_processor *opp) 43890075Sobrien{ 43990075Sobrien struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 44090075Sobrien uint32_t fmt_mem_cntl_value; 44190075Sobrien 44290075Sobrien /* Program source select*/ 44390075Sobrien /* Use HW default source select for FMT_MEMORYx_CONTROL */ 44490075Sobrien /* Use that value for FMT_SRC_SELECT as well*/ 44590075Sobrien REG_GET(CONTROL, 44690075Sobrien FMT420_MEM0_SOURCE_SEL, &fmt_mem_cntl_value); 44790075Sobrien 448169689Skan REG_UPDATE(FMT_CONTROL, 44990075Sobrien FMT_SRC_SELECT, fmt_mem_cntl_value); 450169689Skan 45190075Sobrien /* Turn on the memory */ 45290075Sobrien REG_UPDATE(CONTROL, 45390075Sobrien FMT420_MEM0_PWR_FORCE, 0); 45490075Sobrien} 45590075Sobrien 45690075Sobrienvoid dce110_opp_set_dyn_expansion( 45790075Sobrien struct output_pixel_processor *opp, 458117395Skan enum dc_color_space color_sp, 459117395Skan enum dc_color_depth color_dpth, 46090075Sobrien enum signal_type signal) 461132718Skan{ 462132718Skan struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 463117395Skan 464132718Skan REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, 465132718Skan FMT_DYNAMIC_EXP_EN, 0, 466169689Skan FMT_DYNAMIC_EXP_MODE, 0); 467169689Skan 468132718Skan /*00 - 10-bit -> 12-bit dynamic expansion*/ 469169689Skan /*01 - 8-bit -> 12-bit dynamic expansion*/ 470169689Skan if (signal == SIGNAL_TYPE_HDMI_TYPE_A || 471169689Skan signal == SIGNAL_TYPE_DISPLAY_PORT || 472169689Skan signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { 473169689Skan switch (color_dpth) { 474169689Skan case COLOR_DEPTH_888: 475132718Skan REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, 476132718Skan FMT_DYNAMIC_EXP_EN, 1, 477132718Skan FMT_DYNAMIC_EXP_MODE, 1); 478169689Skan break; 479132718Skan case COLOR_DEPTH_101010: 480132718Skan REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, 481132718Skan FMT_DYNAMIC_EXP_EN, 1, 482117395Skan FMT_DYNAMIC_EXP_MODE, 0); 483117395Skan break; 484117395Skan case COLOR_DEPTH_121212: 485146895Skan REG_UPDATE_2( 486117395Skan FMT_DYNAMIC_EXP_CNTL, 487132718Skan FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/ 488132718Skan FMT_DYNAMIC_EXP_MODE, 0); 489132718Skan break; 490132718Skan default: 491132718Skan break; 492169689Skan } 493169689Skan } 494169689Skan} 495169689Skan 496169689Skanstatic void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp) 497169689Skan{ 498169689Skan struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 499169689Skan 500169689Skan /* clear previous phase lock status*/ 501169689Skan REG_UPDATE(FMT_CONTROL, 502169689Skan FMT_420_PIXEL_PHASE_LOCKED_CLEAR, 1); 503169689Skan 504169689Skan /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/ 505169689Skan REG_WAIT(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, 1, 10, 10); 506169689Skan 507169689Skan} 508169689Skan 509169689Skanvoid dce110_opp_program_fmt( 510169689Skan struct output_pixel_processor *opp, 511169689Skan struct bit_depth_reduction_params *fmt_bit_depth, 512169689Skan struct clamping_and_pixel_encoding_params *clamping) 513169689Skan{ 514169689Skan /* dithering is affected by <CrtcSourceSelect>, hence should be 515169689Skan * programmed afterwards */ 516169689Skan 517169689Skan if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) 518169689Skan program_formatter_420_memory(opp); 519169689Skan 520169689Skan dce110_opp_program_bit_depth_reduction( 521169689Skan opp, 522169689Skan fmt_bit_depth); 523169689Skan 524169689Skan dce110_opp_program_clamping_and_pixel_encoding( 525169689Skan opp, 526169689Skan clamping); 527169689Skan 528169689Skan if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) 529169689Skan program_formatter_reset_dig_resync_fifo(opp); 530169689Skan 531169689Skan return; 532169689Skan} 533169689Skan 534169689Skan 535169689Skan 536169689Skan 537169689Skan 538169689Skan/*****************************************/ 539169689Skan/* Constructor, Destructor */ 540169689Skan/*****************************************/ 541169689Skan 542169689Skanstatic const struct opp_funcs funcs = { 543169689Skan .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, 544169689Skan .opp_destroy = dce110_opp_destroy, 545169689Skan .opp_program_fmt = dce110_opp_program_fmt, 546169689Skan .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction 547169689Skan}; 548169689Skan 549169689Skanvoid dce110_opp_construct(struct dce110_opp *opp110, 550169689Skan struct dc_context *ctx, 551169689Skan uint32_t inst, 552169689Skan const struct dce_opp_registers *regs, 553169689Skan const struct dce_opp_shift *opp_shift, 554169689Skan const struct dce_opp_mask *opp_mask) 555169689Skan{ 556169689Skan opp110->base.funcs = &funcs; 557169689Skan 558169689Skan opp110->base.ctx = ctx; 559169689Skan 560169689Skan opp110->base.inst = inst; 561169689Skan 562169689Skan opp110->regs = regs; 56390075Sobrien opp110->opp_shift = opp_shift; 564169689Skan opp110->opp_mask = opp_mask; 565169689Skan} 566169689Skan 567169689Skanvoid dce110_opp_destroy(struct output_pixel_processor **opp) 568169689Skan{ 569169689Skan if (*opp) 570169689Skan kfree(FROM_DCE11_OPP(*opp)); 571169689Skan *opp = NULL; 572169689Skan} 573169689Skan 574169689Skan