1 /* 2 * Copyright 2012-15 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: AMD 23 * 24 */ 25 26 #include "dm_services.h" 27 #include "dcn20_opp.h" 28 #include "reg_helper.h" 29 30 #define REG(reg) \ 31 (oppn20->regs->reg) 32 33 #undef FN 34 #define FN(reg_name, field_name) \ 35 oppn20->opp_shift->field_name, oppn20->opp_mask->field_name 36 37 #define CTX \ 38 oppn20->base.ctx 39 40 41 void opp2_set_disp_pattern_generator( 42 struct output_pixel_processor *opp, 43 enum controller_dp_test_pattern test_pattern, 44 enum dc_color_depth color_depth, 45 const struct tg_color *solid_color, 46 int width, 47 int height) 48 { 49 struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp); 50 enum test_pattern_color_format bit_depth; 51 enum test_pattern_dyn_range dyn_range; 52 enum test_pattern_mode mode; 53 54 /* color ramp generator mixes 16-bits color */ 55 uint32_t src_bpc = 16; 56 /* requested bpc */ 57 uint32_t dst_bpc; 58 uint32_t index; 59 /* RGB values of the color bars. 60 * Produce two RGB colors: RGB0 - white (all Fs) 61 * and RGB1 - black (all 0s) 62 * (three RGB components for two colors) 63 */ 64 uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 65 0x0000, 0x0000}; 66 /* dest color (converted to the specified color format) */ 67 uint16_t dst_color[6]; 68 uint32_t inc_base; 69 70 /* translate to bit depth */ 71 switch (color_depth) { 72 case COLOR_DEPTH_666: 73 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6; 74 break; 75 case COLOR_DEPTH_888: 76 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; 77 break; 78 case COLOR_DEPTH_101010: 79 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10; 80 break; 81 case COLOR_DEPTH_121212: 82 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12; 83 break; 84 default: 85 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; 86 break; 87 } 88 89 /* set DPG dimentions */ 90 REG_SET_2(DPG_DIMENSIONS, 0, 91 DPG_ACTIVE_WIDTH, width, 92 DPG_ACTIVE_HEIGHT, height); 93 94 switch (test_pattern) { 95 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES: 96 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA: 97 { 98 dyn_range = (test_pattern == 99 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ? 100 TEST_PATTERN_DYN_RANGE_CEA : 101 TEST_PATTERN_DYN_RANGE_VESA); 102 103 REG_UPDATE_6(DPG_CONTROL, 104 DPG_EN, 1, 105 DPG_MODE, TEST_PATTERN_MODE_COLORSQUARES_RGB, 106 DPG_DYNAMIC_RANGE, dyn_range, 107 DPG_BIT_DEPTH, bit_depth, 108 DPG_VRES, 6, 109 DPG_HRES, 6); 110 } 111 break; 112 113 case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS: 114 case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS: 115 { 116 mode = (test_pattern == 117 CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ? 118 TEST_PATTERN_MODE_VERTICALBARS : 119 TEST_PATTERN_MODE_HORIZONTALBARS); 120 121 switch (bit_depth) { 122 case TEST_PATTERN_COLOR_FORMAT_BPC_6: 123 dst_bpc = 6; 124 break; 125 case TEST_PATTERN_COLOR_FORMAT_BPC_8: 126 dst_bpc = 8; 127 break; 128 case TEST_PATTERN_COLOR_FORMAT_BPC_10: 129 dst_bpc = 10; 130 break; 131 default: 132 dst_bpc = 8; 133 break; 134 } 135 136 /* adjust color to the required colorFormat */ 137 for (index = 0; index < 6; index++) { 138 /* dst = 2^dstBpc * src / 2^srcBpc = src >> 139 * (srcBpc - dstBpc); 140 */ 141 dst_color[index] = 142 src_color[index] >> (src_bpc - dst_bpc); 143 /* DPG_COLOUR registers are 16-bit MSB aligned value with bits 3:0 hardwired to ZERO. 144 * XXXXXXXXXX000000 for 10 bit, 145 * XXXXXXXX00000000 for 8 bit, 146 * XXXXXX0000000000 for 6 bits 147 */ 148 dst_color[index] <<= (16 - dst_bpc); 149 } 150 151 REG_SET_2(DPG_COLOUR_R_CR, 0, 152 DPG_COLOUR1_R_CR, dst_color[0], 153 DPG_COLOUR0_R_CR, dst_color[3]); 154 REG_SET_2(DPG_COLOUR_G_Y, 0, 155 DPG_COLOUR1_G_Y, dst_color[1], 156 DPG_COLOUR0_G_Y, dst_color[4]); 157 REG_SET_2(DPG_COLOUR_B_CB, 0, 158 DPG_COLOUR1_B_CB, dst_color[2], 159 DPG_COLOUR0_B_CB, dst_color[5]); 160 161 /* enable test pattern */ 162 REG_UPDATE_6(DPG_CONTROL, 163 DPG_EN, 1, 164 DPG_MODE, mode, 165 DPG_DYNAMIC_RANGE, 0, 166 DPG_BIT_DEPTH, bit_depth, 167 DPG_VRES, 0, 168 DPG_HRES, 0); 169 } 170 break; 171 172 case CONTROLLER_DP_TEST_PATTERN_COLORRAMP: 173 { 174 mode = (bit_depth == 175 TEST_PATTERN_COLOR_FORMAT_BPC_10 ? 176 TEST_PATTERN_MODE_DUALRAMP_RGB : 177 TEST_PATTERN_MODE_SINGLERAMP_RGB); 178 179 switch (bit_depth) { 180 case TEST_PATTERN_COLOR_FORMAT_BPC_6: 181 dst_bpc = 6; 182 break; 183 case TEST_PATTERN_COLOR_FORMAT_BPC_8: 184 dst_bpc = 8; 185 break; 186 case TEST_PATTERN_COLOR_FORMAT_BPC_10: 187 dst_bpc = 10; 188 break; 189 default: 190 dst_bpc = 8; 191 break; 192 } 193 194 /* increment for the first ramp for one color gradation 195 * 1 gradation for 6-bit color is 2^10 196 * gradations in 16-bit color 197 */ 198 inc_base = (src_bpc - dst_bpc); 199 200 switch (bit_depth) { 201 case TEST_PATTERN_COLOR_FORMAT_BPC_6: 202 { 203 REG_SET_3(DPG_RAMP_CONTROL, 0, 204 DPG_RAMP0_OFFSET, 0, 205 DPG_INC0, inc_base, 206 DPG_INC1, 0); 207 REG_UPDATE_2(DPG_CONTROL, 208 DPG_VRES, 6, 209 DPG_HRES, 6); 210 } 211 break; 212 case TEST_PATTERN_COLOR_FORMAT_BPC_8: 213 { 214 REG_SET_3(DPG_RAMP_CONTROL, 0, 215 DPG_RAMP0_OFFSET, 0, 216 DPG_INC0, inc_base, 217 DPG_INC1, 0); 218 REG_UPDATE_2(DPG_CONTROL, 219 DPG_VRES, 6, 220 DPG_HRES, 8); 221 } 222 break; 223 case TEST_PATTERN_COLOR_FORMAT_BPC_10: 224 { 225 REG_SET_3(DPG_RAMP_CONTROL, 0, 226 DPG_RAMP0_OFFSET, 384 << 6, 227 DPG_INC0, inc_base, 228 DPG_INC1, inc_base + 2); 229 REG_UPDATE_2(DPG_CONTROL, 230 DPG_VRES, 5, 231 DPG_HRES, 8); 232 } 233 break; 234 default: 235 break; 236 } 237 238 /* enable test pattern */ 239 REG_UPDATE_4(DPG_CONTROL, 240 DPG_EN, 1, 241 DPG_MODE, mode, 242 DPG_DYNAMIC_RANGE, 0, 243 DPG_BIT_DEPTH, bit_depth); 244 } 245 break; 246 case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE: 247 { 248 REG_WRITE(DPG_CONTROL, 0); 249 REG_WRITE(DPG_COLOUR_R_CR, 0); 250 REG_WRITE(DPG_COLOUR_G_Y, 0); 251 REG_WRITE(DPG_COLOUR_B_CB, 0); 252 REG_WRITE(DPG_RAMP_CONTROL, 0); 253 } 254 break; 255 case CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR: 256 { 257 opp2_dpg_set_blank_color(opp, solid_color); 258 REG_UPDATE_2(DPG_CONTROL, 259 DPG_EN, 1, 260 DPG_MODE, TEST_PATTERN_MODE_HORIZONTALBARS); 261 262 REG_SET_2(DPG_DIMENSIONS, 0, 263 DPG_ACTIVE_WIDTH, width, 264 DPG_ACTIVE_HEIGHT, height); 265 } 266 break; 267 default: 268 break; 269 270 } 271 } 272 273 void opp2_dpg_set_blank_color( 274 struct output_pixel_processor *opp, 275 const struct tg_color *color) 276 { 277 struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp); 278 279 /* 16-bit MSB aligned value. Bits 3:0 of this field are hardwired to ZERO */ 280 ASSERT(color); 281 REG_SET_2(DPG_COLOUR_B_CB, 0, 282 DPG_COLOUR1_B_CB, color->color_b_cb << 6, 283 DPG_COLOUR0_B_CB, color->color_b_cb << 6); 284 REG_SET_2(DPG_COLOUR_G_Y, 0, 285 DPG_COLOUR1_G_Y, color->color_g_y << 6, 286 DPG_COLOUR0_G_Y, color->color_g_y << 6); 287 REG_SET_2(DPG_COLOUR_R_CR, 0, 288 DPG_COLOUR1_R_CR, color->color_r_cr << 6, 289 DPG_COLOUR0_R_CR, color->color_r_cr << 6); 290 } 291 292 bool opp2_dpg_is_blanked(struct output_pixel_processor *opp) 293 { 294 struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp); 295 uint32_t dpg_en, dpg_mode; 296 uint32_t double_buffer_pending; 297 298 REG_GET_2(DPG_CONTROL, 299 DPG_EN, &dpg_en, 300 DPG_MODE, &dpg_mode); 301 302 REG_GET(DPG_STATUS, 303 DPG_DOUBLE_BUFFER_PENDING, &double_buffer_pending); 304 305 return (dpg_en == 1) && 306 (double_buffer_pending == 0); 307 } 308 309 void opp2_program_left_edge_extra_pixel ( 310 struct output_pixel_processor *opp, 311 bool count) 312 { 313 struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp); 314 315 /* Specifies the number of extra left edge pixels that are supplied to 316 * the 422 horizontal chroma sub-sample filter. 317 * Note that when left edge pixel is not "0", fmt pixel encoding can be in either 420 or 422 mode 318 * */ 319 REG_UPDATE(FMT_422_CONTROL, FMT_LEFT_EDGE_EXTRA_PIXEL_COUNT, count); 320 } 321 322 /*****************************************/ 323 /* Constructor, Destructor */ 324 /*****************************************/ 325 326 static struct opp_funcs dcn20_opp_funcs = { 327 .opp_set_dyn_expansion = opp1_set_dyn_expansion, 328 .opp_program_fmt = opp1_program_fmt, 329 .opp_program_bit_depth_reduction = opp1_program_bit_depth_reduction, 330 .opp_program_stereo = opp1_program_stereo, 331 .opp_pipe_clock_control = opp1_pipe_clock_control, 332 .opp_set_disp_pattern_generator = opp2_set_disp_pattern_generator, 333 .dpg_is_blanked = opp2_dpg_is_blanked, 334 .opp_dpg_set_blank_color = opp2_dpg_set_blank_color, 335 .opp_destroy = opp1_destroy, 336 .opp_program_left_edge_extra_pixel = opp2_program_left_edge_extra_pixel, 337 }; 338 339 void dcn20_opp_construct(struct dcn20_opp *oppn20, 340 struct dc_context *ctx, 341 uint32_t inst, 342 const struct dcn20_opp_registers *regs, 343 const struct dcn20_opp_shift *opp_shift, 344 const struct dcn20_opp_mask *opp_mask) 345 { 346 oppn20->base.ctx = ctx; 347 oppn20->base.inst = inst; 348 oppn20->base.funcs = &dcn20_opp_funcs; 349 350 oppn20->regs = regs; 351 oppn20->opp_shift = opp_shift; 352 oppn20->opp_mask = opp_mask; 353 } 354 355