Home | History | Annotate | Line # | Download | only in dcn20
      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 
     46 void 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 
    292 void 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 
    311 bool 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 
    328 void 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 
    345 static 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 
    358 void 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