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