File Index
Files and directories
Sign in
FILE

dcn20_opp.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/display/dc/opp/dcn20/dcn20_opp.c C
  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 "core_types.h"
 27#include "dm_services.h"
 28#include "dcn20_opp.h"
 29#include "reg_helper.h"
 30
 31#define REG(reg) \
 32	(oppn20->regs->reg)
 33
 34#undef FN
 35#define FN(reg_name, field_name) \
 36	oppn20->opp_shift->field_name, oppn20->opp_mask->field_name
 37
 38#define CTX \
 39	oppn20->base.ctx
 40
 41
 42void opp2_set_disp_pattern_generator(
 43		struct output_pixel_processor *opp,
 44		enum controller_dp_test_pattern test_pattern,
 45		enum controller_dp_color_space color_space,
 46		enum dc_color_depth color_depth,
 47		const struct tg_color *solid_color,
 48		int width,
 49		int height,
 50		int offset)
 51{
 52	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
 53	enum test_pattern_color_format bit_depth;
 54	enum test_pattern_dyn_range dyn_range;
 55	enum test_pattern_mode mode;
 56
 57	/* color ramp generator mixes 16-bits color */
 58	uint32_t src_bpc = 16;
 59	/* requested bpc */
 60	uint32_t dst_bpc;
 61	uint32_t index;
 62	/* RGB values of the color bars.
 63	 * Produce two RGB colors: RGB0 - white (all Fs)
 64	 * and RGB1 - black (all 0s)
 65	 * (three RGB components for two colors)
 66	 */
 67	uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
 68						0x0000, 0x0000};
 69	/* dest color (converted to the specified color format) */
 70	uint16_t dst_color[6];
 71	uint32_t inc_base;
 72
 73	/* translate to bit depth */
 74	switch (color_depth) {
 75	case COLOR_DEPTH_666:
 76		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
 77	break;
 78	case COLOR_DEPTH_888:
 79		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 80	break;
 81	case COLOR_DEPTH_101010:
 82		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
 83	break;
 84	case COLOR_DEPTH_121212:
 85		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
 86	break;
 87	default:
 88		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 89	break;
 90	}
 91
 92	/* set DPG dimentions */
 93	REG_SET_2(DPG_DIMENSIONS, 0,
 94		DPG_ACTIVE_WIDTH, width,
 95		DPG_ACTIVE_HEIGHT, height);
 96
 97	/* set DPG offset */
 98	REG_SET_2(DPG_OFFSET_SEGMENT, 0,
 99		DPG_X_OFFSET, offset,
100		DPG_SEGMENT_WIDTH, 0);
101
102	switch (test_pattern) {
103	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
104	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
105	{
106		dyn_range = (test_pattern ==
107				CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
108				TEST_PATTERN_DYN_RANGE_CEA :
109				TEST_PATTERN_DYN_RANGE_VESA);
110
111		switch (color_space) {
112		case CONTROLLER_DP_COLOR_SPACE_YCBCR601:
113			mode = TEST_PATTERN_MODE_COLORSQUARES_YCBCR601;
114		break;
115		case CONTROLLER_DP_COLOR_SPACE_YCBCR709:
116			mode = TEST_PATTERN_MODE_COLORSQUARES_YCBCR709;
117		break;
118		case CONTROLLER_DP_COLOR_SPACE_RGB:
119		default:
120			mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
121		break;
122		}
123
124		REG_UPDATE_6(DPG_CONTROL,
125			DPG_EN, 1,
126			DPG_MODE, mode,
127			DPG_DYNAMIC_RANGE, dyn_range,
128			DPG_BIT_DEPTH, bit_depth,
129			DPG_VRES, 6,
130			DPG_HRES, 6);
131	}
132	break;
133
134	case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
135	case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
136	{
137		mode = (test_pattern ==
138			CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
139			TEST_PATTERN_MODE_VERTICALBARS :
140			TEST_PATTERN_MODE_HORIZONTALBARS);
141
142		switch (bit_depth) {
143		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
144			dst_bpc = 6;
145		break;
146		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
147			dst_bpc = 8;
148		break;
149		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
150			dst_bpc = 10;
151		break;
152		default:
153			dst_bpc = 8;
154		break;
155		}
156
157		/* adjust color to the required colorFormat */
158		for (index = 0; index < 6; index++) {
159			/* dst = 2^dstBpc * src / 2^srcBpc = src >>
160			 * (srcBpc - dstBpc);
161			 */
162			dst_color[index] =
163				src_color[index] >> (src_bpc - dst_bpc);
164		/* DPG_COLOUR registers are 16-bit MSB aligned value with bits 3:0 hardwired to ZERO.
165		 * XXXXXXXXXX000000 for 10 bit,
166		 * XXXXXXXX00000000 for 8 bit,
167		 * XXXXXX0000000000 for 6 bits
168		 */
169			dst_color[index] <<= (16 - dst_bpc);
170		}
171
172		REG_SET_2(DPG_COLOUR_R_CR, 0,
173				DPG_COLOUR1_R_CR, dst_color[0],
174				DPG_COLOUR0_R_CR, dst_color[3]);
175		REG_SET_2(DPG_COLOUR_G_Y, 0,
176				DPG_COLOUR1_G_Y, dst_color[1],
177				DPG_COLOUR0_G_Y, dst_color[4]);
178		REG_SET_2(DPG_COLOUR_B_CB, 0,
179				DPG_COLOUR1_B_CB, dst_color[2],
180				DPG_COLOUR0_B_CB, dst_color[5]);
181
182		/* enable test pattern */
183		REG_UPDATE_6(DPG_CONTROL,
184			DPG_EN, 1,
185			DPG_MODE, mode,
186			DPG_DYNAMIC_RANGE, 0,
187			DPG_BIT_DEPTH, bit_depth,
188			DPG_VRES, 0,
189			DPG_HRES, 0);
190	}
191	break;
192
193	case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
194	{
195		mode = (bit_depth ==
196			TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
197			TEST_PATTERN_MODE_DUALRAMP_RGB :
198			TEST_PATTERN_MODE_SINGLERAMP_RGB);
199
200		switch (bit_depth) {
201		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
202			dst_bpc = 6;
203		break;
204		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
205			dst_bpc = 8;
206		break;
207		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
208			dst_bpc = 10;
209		break;
210		default:
211			dst_bpc = 8;
212		break;
213		}
214
215		/* increment for the first ramp for one color gradation
216		 * 1 gradation for 6-bit color is 2^10
217		 * gradations in 16-bit color
218		 */
219		inc_base = (src_bpc - dst_bpc);
220
221		switch (bit_depth) {
222		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
223		{
224			REG_SET_3(DPG_RAMP_CONTROL, 0,
225				DPG_RAMP0_OFFSET, 0,
226				DPG_INC0, inc_base,
227				DPG_INC1, 0);
228			REG_UPDATE_2(DPG_CONTROL,
229				DPG_VRES, 6,
230				DPG_HRES, 6);
231		}
232		break;
233		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
234		{
235			REG_SET_3(DPG_RAMP_CONTROL, 0,
236				DPG_RAMP0_OFFSET, 0,
237				DPG_INC0, inc_base,
238				DPG_INC1, 0);
239			REG_UPDATE_2(DPG_CONTROL,
240				DPG_VRES, 6,
241				DPG_HRES, 8);
242		}
243		break;
244		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
245		{
246			REG_SET_3(DPG_RAMP_CONTROL, 0,
247				DPG_RAMP0_OFFSET, 384 << 6,
248				DPG_INC0, inc_base,
249				DPG_INC1, inc_base + 2);
250			REG_UPDATE_2(DPG_CONTROL,
251				DPG_VRES, 5,
252				DPG_HRES, 8);
253		}
254		break;
255		default:
256		break;
257		}
258
259		/* enable test pattern */
260		REG_UPDATE_4(DPG_CONTROL,
261			DPG_EN, 1,
262			DPG_MODE, mode,
263			DPG_DYNAMIC_RANGE, 0,
264			DPG_BIT_DEPTH, bit_depth);
265	}
266	break;
267	case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
268	{
269		REG_WRITE(DPG_CONTROL, 0);
270		REG_WRITE(DPG_COLOUR_R_CR, 0);
271		REG_WRITE(DPG_COLOUR_G_Y, 0);
272		REG_WRITE(DPG_COLOUR_B_CB, 0);
273		REG_WRITE(DPG_RAMP_CONTROL, 0);
274	}
275	break;
276	case CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR:
277	{
278		opp2_dpg_set_blank_color(opp, solid_color);
279		REG_UPDATE_2(DPG_CONTROL,
280				DPG_EN, 1,
281				DPG_MODE, TEST_PATTERN_MODE_HORIZONTALBARS);
282
283		REG_SET_2(DPG_DIMENSIONS, 0,
284				DPG_ACTIVE_WIDTH, width,
285				DPG_ACTIVE_HEIGHT, height);
286	}
287	break;
288	default:
289		break;
290
291	}
292}
293
294void opp2_program_dpg_dimensions(
295		struct output_pixel_processor *opp,
296		int width, int height)
297{
298	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
299
300	REG_SET_2(DPG_DIMENSIONS, 0,
301		DPG_ACTIVE_WIDTH, width,
302		DPG_ACTIVE_HEIGHT, height);
303}
304
305void opp2_dpg_set_blank_color(
306		struct output_pixel_processor *opp,
307		const struct tg_color *color)
308{
309	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
310
311	/* 16-bit MSB aligned value. Bits 3:0 of this field are hardwired to ZERO */
312	ASSERT(color);
313	REG_SET_2(DPG_COLOUR_B_CB, 0,
314			DPG_COLOUR1_B_CB, color->color_b_cb << 6,
315			DPG_COLOUR0_B_CB, color->color_b_cb << 6);
316	REG_SET_2(DPG_COLOUR_G_Y, 0,
317			DPG_COLOUR1_G_Y, color->color_g_y << 6,
318			DPG_COLOUR0_G_Y, color->color_g_y << 6);
319	REG_SET_2(DPG_COLOUR_R_CR, 0,
320			DPG_COLOUR1_R_CR, color->color_r_cr << 6,
321			DPG_COLOUR0_R_CR, color->color_r_cr << 6);
322}
323
324bool opp2_dpg_is_blanked(struct output_pixel_processor *opp)
325{
326	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
327	uint32_t dpg_en, dpg_mode;
328	uint32_t double_buffer_pending;
329
330	REG_GET_2(DPG_CONTROL,
331			DPG_EN, &dpg_en,
332			DPG_MODE, &dpg_mode);
333
334	REG_GET(DPG_STATUS,
335			DPG_DOUBLE_BUFFER_PENDING, &double_buffer_pending);
336
337	return (dpg_en == 1) &&
338		(double_buffer_pending == 0);
339}
340
341bool opp2_dpg_is_pending(struct output_pixel_processor *opp)
342{
343	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
344	uint32_t double_buffer_pending;
345	uint32_t dpg_en;
346
347	REG_GET(DPG_CONTROL, DPG_EN, &dpg_en);
348
349	REG_GET(DPG_STATUS, DPG_DOUBLE_BUFFER_PENDING, &double_buffer_pending);
350
351	return (dpg_en == 1 && double_buffer_pending == 1);
352}
353
354void opp2_program_left_edge_extra_pixel(
355		struct output_pixel_processor *opp,
356		enum dc_pixel_encoding pixel_encoding,
357		bool is_primary)
358{
359	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
360	uint32_t count = opp2_get_left_edge_extra_pixel_count(opp, pixel_encoding, is_primary);
361
362	/*
363	 * Specifies the number of extra left edge pixels that are supplied to
364	 * the 422 horizontal chroma sub-sample filter.
365	 */
366	REG_UPDATE(FMT_422_CONTROL, FMT_LEFT_EDGE_EXTRA_PIXEL_COUNT, count);
367}
368
369uint32_t opp2_get_left_edge_extra_pixel_count(struct output_pixel_processor *opp,
370		enum dc_pixel_encoding pixel_encoding, bool is_primary)
371{
372	if ((pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420) &&
373			!opp->ctx->dc->debug.force_chroma_subsampling_1tap &&
374			!is_primary)
375		return 1;
376	else
377		return 0;
378}
379
380void opp2_read_reg_state(struct output_pixel_processor *opp, struct dcn_opp_reg_state *opp_reg_state)
381{
382	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
383
384	opp_reg_state->dpg_control = REG_READ(DPG_CONTROL);
385	opp_reg_state->fmt_control = REG_READ(FMT_CONTROL);
386	opp_reg_state->opp_pipe_control = REG_READ(OPP_PIPE_CONTROL);
387	opp_reg_state->opp_pipe_crc_control = REG_READ(OPP_PIPE_CRC_CONTROL);
388	opp_reg_state->oppbuf_control = REG_READ(OPPBUF_CONTROL);
389	opp_reg_state->dscrm_dsc_forward_config = REG_READ(DSCRM_DSC_FORWARD_CONFIG);
390}
391
392/*****************************************/
393/* Constructor, Destructor               */
394/*****************************************/
395
396static struct opp_funcs dcn20_opp_funcs = {
397		.opp_set_dyn_expansion = opp1_set_dyn_expansion,
398		.opp_program_fmt = opp1_program_fmt,
399		.opp_program_bit_depth_reduction = opp1_program_bit_depth_reduction,
400		.opp_program_stereo = opp1_program_stereo,
401		.opp_pipe_clock_control = opp1_pipe_clock_control,
402		.opp_set_disp_pattern_generator = opp2_set_disp_pattern_generator,
403		.opp_program_dpg_dimensions = opp2_program_dpg_dimensions,
404		.dpg_is_blanked = opp2_dpg_is_blanked,
405		.dpg_is_pending = opp2_dpg_is_pending,
406		.opp_dpg_set_blank_color = opp2_dpg_set_blank_color,
407		.opp_destroy = opp1_destroy,
408		.opp_program_left_edge_extra_pixel = opp2_program_left_edge_extra_pixel,
409		.opp_get_left_edge_extra_pixel_count = opp2_get_left_edge_extra_pixel_count,
410		.opp_read_reg_state = opp2_read_reg_state
411};
412
413void dcn20_opp_construct(struct dcn20_opp *oppn20,
414	struct dc_context *ctx,
415	uint32_t inst,
416	const struct dcn20_opp_registers *regs,
417	const struct dcn20_opp_shift *opp_shift,
418	const struct dcn20_opp_mask *opp_mask)
419{
420	oppn20->base.ctx = ctx;
421	oppn20->base.inst = inst;
422	oppn20->base.funcs = &dcn20_opp_funcs;
423
424	oppn20->regs = regs;
425	oppn20->opp_shift = opp_shift;
426	oppn20->opp_mask = opp_mask;
427}
428
~/ Read-only file preview.