1/* SPDX-License-Identifier: MIT */
2/*
3 * Copyright 2023 Advanced Micro Devices, Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 */
24
25
26#include "dc_bios_types.h"
27#include "dcn30/dcn30_dio_stream_encoder.h"
28#include "dcn314/dcn314_dio_stream_encoder.h"
29#include "dcn32/dcn32_dio_stream_encoder.h"
30#include "dcn35_dio_stream_encoder.h"
31#include "reg_helper.h"
32#include "hw_shared.h"
33#include "link.h"
34#include "dpcd_defs.h"
35
36#define DC_LOGGER \
37		enc1->base.ctx->logger
38
39#define REG(reg)\
40	(enc1->regs->reg)
41
42#undef FN
43#define FN(reg_name, field_name) \
44	enc1->se_shift->field_name, enc1->se_mask->field_name
45
46#define VBI_LINE_0 0
47#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000
48
49#define CTX \
50	enc1->base.ctx
51/* setup stream encoder in dvi mode */
52static void enc35_stream_encoder_dvi_set_stream_attribute(
53	struct stream_encoder *enc,
54	struct dc_crtc_timing *crtc_timing,
55	bool is_dual_link)
56{
57	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
58
59	if (!enc->ctx->dc->debug.avoid_vbios_exec_table) {
60		struct bp_encoder_control cntl = {0};
61
62		cntl.action = ENCODER_CONTROL_SETUP;
63		cntl.engine_id = enc1->base.id;
64		cntl.signal = is_dual_link ?
65			SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK;
66		cntl.enable_dp_audio = false;
67		cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10;
68		cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR;
69
70		if (enc1->base.bp->funcs->encoder_control(
71				enc1->base.bp, &cntl) != BP_RESULT_OK)
72			return;
73
74	} else {
75
76		//Set pattern for clock channel, default vlue 0x63 does not work
77		REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F);
78
79		//DIG_BE_TMDS_DVI_MODE : TMDS-DVI mode is already set in link_encoder_setup
80
81		//DIG_SOURCE_SELECT is already set in dig_connect_to_otg
82
83		/* DIG_START is removed from the register spec */
84	}
85
86	ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB);
87	ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888);
88	enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing);
89}
90/* setup stream encoder in hdmi mode */
91static void enc35_stream_encoder_hdmi_set_stream_attribute(
92	struct stream_encoder *enc,
93	struct dc_crtc_timing *crtc_timing,
94	int actual_pix_clk_khz,
95	bool enable_audio)
96{
97	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
98
99	if (!enc->ctx->dc->debug.avoid_vbios_exec_table) {
100		struct bp_encoder_control cntl = {0};
101
102		cntl.action = ENCODER_CONTROL_SETUP;
103		cntl.engine_id = enc1->base.id;
104		cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A;
105		cntl.enable_dp_audio = enable_audio;
106		cntl.pixel_clock = actual_pix_clk_khz;
107		cntl.lanes_number = LANE_COUNT_FOUR;
108
109		if (enc1->base.bp->funcs->encoder_control(
110				enc1->base.bp, &cntl) != BP_RESULT_OK)
111			return;
112
113	} else {
114
115		//Set pattern for clock channel, default vlue 0x63 does not work
116		REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F);
117
118		//DIG_BE_TMDS_HDMI_MODE : TMDS-HDMI mode is already set in link_encoder_setup
119
120		//DIG_SOURCE_SELECT is already set in dig_connect_to_otg
121
122		/* DIG_START is removed from the register spec */
123		enc314_enable_fifo(enc);
124	}
125
126	/* Configure pixel encoding */
127	enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing);
128
129	/* setup HDMI engine */
130	REG_UPDATE_6(HDMI_CONTROL,
131		HDMI_PACKET_GEN_VERSION, 1,
132		HDMI_KEEPOUT_MODE, 1,
133		HDMI_DEEP_COLOR_ENABLE, 0,
134		HDMI_DATA_SCRAMBLE_EN, 0,
135		HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1,
136		HDMI_CLOCK_CHANNEL_RATE, 0);
137
138	/* Configure color depth */
139	switch (crtc_timing->display_color_depth) {
140	case COLOR_DEPTH_888:
141		REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0);
142		break;
143	case COLOR_DEPTH_101010:
144		if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
145			REG_UPDATE_2(HDMI_CONTROL,
146					HDMI_DEEP_COLOR_DEPTH, 1,
147					HDMI_DEEP_COLOR_ENABLE, 0);
148		} else {
149			REG_UPDATE_2(HDMI_CONTROL,
150					HDMI_DEEP_COLOR_DEPTH, 1,
151					HDMI_DEEP_COLOR_ENABLE, 1);
152			}
153		break;
154	case COLOR_DEPTH_121212:
155		if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
156			REG_UPDATE_2(HDMI_CONTROL,
157					HDMI_DEEP_COLOR_DEPTH, 2,
158					HDMI_DEEP_COLOR_ENABLE, 0);
159		} else {
160			REG_UPDATE_2(HDMI_CONTROL,
161					HDMI_DEEP_COLOR_DEPTH, 2,
162					HDMI_DEEP_COLOR_ENABLE, 1);
163			}
164		break;
165	case COLOR_DEPTH_161616:
166		REG_UPDATE_2(HDMI_CONTROL,
167				HDMI_DEEP_COLOR_DEPTH, 3,
168				HDMI_DEEP_COLOR_ENABLE, 1);
169		break;
170	default:
171		break;
172	}
173
174	if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) {
175		/* enable HDMI data scrambler
176		 * HDMI_CLOCK_CHANNEL_RATE_MORE_340M
177		 * Clock channel frequency is 1/4 of character rate.
178		 */
179		REG_UPDATE_2(HDMI_CONTROL,
180			HDMI_DATA_SCRAMBLE_EN, 1,
181			HDMI_CLOCK_CHANNEL_RATE, 1);
182	} else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) {
183
184		/* TODO: New feature for DCE11, still need to implement */
185
186		/* enable HDMI data scrambler
187		 * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE
188		 * Clock channel frequency is the same
189		 * as character rate
190		 */
191		REG_UPDATE_2(HDMI_CONTROL,
192			HDMI_DATA_SCRAMBLE_EN, 1,
193			HDMI_CLOCK_CHANNEL_RATE, 0);
194	}
195
196
197	/* Enable transmission of General Control packet on every frame */
198	REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL,
199		HDMI_GC_CONT, 1,
200		HDMI_GC_SEND, 1,
201		HDMI_NULL_SEND, 1);
202
203	/* Disable Audio Content Protection packet transmission */
204	REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0);
205
206	/* following belongs to audio */
207	/* Enable Audio InfoFrame packet transmission. */
208	REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1);
209
210	/* update double-buffered AUDIO_INFO registers immediately */
211	ASSERT(enc->afmt);
212	enc->afmt->funcs->audio_info_immediate_update(enc->afmt);
213
214	/* Select line number on which to send Audio InfoFrame packets */
215	REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE,
216				VBI_LINE_0 + 2);
217
218	/* set HDMI GC AVMUTE */
219	REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0);
220	switch (crtc_timing->pixel_encoding) {
221	case PIXEL_ENCODING_YCBCR422:
222		REG_UPDATE(HDMI_CONTROL, TMDS_PIXEL_ENCODING, 1);
223	break;
224	default:
225		REG_UPDATE(HDMI_CONTROL, TMDS_PIXEL_ENCODING, 0);
226	break;
227	}
228	REG_UPDATE(HDMI_CONTROL, TMDS_COLOR_FORMAT, 0);
229}
230
231
232
233static void enc35_stream_encoder_enable(
234	struct stream_encoder *enc,
235	enum signal_type signal,
236	bool enable)
237{
238	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
239
240	if (enable) {
241		switch (signal) {
242		case SIGNAL_TYPE_DVI_SINGLE_LINK:
243		case SIGNAL_TYPE_DVI_DUAL_LINK:
244			/* TMDS-DVI */
245			REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_MODE, 2);
246			break;
247		case SIGNAL_TYPE_HDMI_TYPE_A:
248			/* TMDS-HDMI */
249			REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_MODE, 3);
250			break;
251		case SIGNAL_TYPE_DISPLAY_PORT_MST:
252			/* DP MST */
253			REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_MODE, 5);
254			break;
255		case SIGNAL_TYPE_EDP:
256		case SIGNAL_TYPE_DISPLAY_PORT:
257			/* DP SST */
258			REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_MODE, 0);
259			break;
260		default:
261			/* invalid mode ! */
262			ASSERT_CRITICAL(false);
263		}
264	}
265}
266
267static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
268{
269	bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420;
270
271	two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
272			&& !timing->dsc_cfg.ycbcr422_simple);
273	return two_pix;
274}
275
276static bool is_h_timing_divisible_by_2(const struct dc_crtc_timing *timing)
277{
278	/* math borrowed from function of same name in inc/resource
279	 * checks if h_timing is divisible by 2
280	 */
281
282	bool divisible = false;
283	uint16_t h_blank_start = 0;
284	uint16_t h_blank_end = 0;
285
286	if (timing) {
287		h_blank_start = timing->h_total - timing->h_front_porch;
288		h_blank_end = h_blank_start - timing->h_addressable;
289
290		/* HTOTAL, Hblank start/end, and Hsync start/end all must be
291		 * divisible by 2 in order for the horizontal timing params
292		 * to be considered divisible by 2. Hsync start is always 0.
293		 */
294		divisible = (timing->h_total % 2 == 0) &&
295				(h_blank_start % 2 == 0) &&
296				(h_blank_end % 2 == 0) &&
297				(timing->h_sync_width % 2 == 0);
298	}
299	return divisible;
300}
301
302static bool is_dp_dig_pixel_rate_div_policy(struct dc *dc, const struct dc_crtc_timing *timing)
303{
304	/* should be functionally the same as dcn32_is_dp_dig_pixel_rate_div_policy for DP encoders*/
305	return is_h_timing_divisible_by_2(timing) &&
306		dc->debug.enable_dp_dig_pixel_rate_div_policy;
307}
308
309static void enc35_stream_encoder_dp_unblank(
310		struct dc_link *link,
311		struct stream_encoder *enc,
312		const struct encoder_unblank_param *param)
313{
314	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
315	struct dc *dc = enc->ctx->dc;
316
317	if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) {
318		uint32_t n_vid = 0x8000;
319		uint32_t m_vid;
320		uint32_t n_multiply = 0;
321		uint32_t pix_per_cycle = 0;
322		uint64_t m_vid_l = n_vid;
323
324		/* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */
325		if (is_two_pixels_per_containter(&param->timing) || param->opp_cnt > 1
326			|| is_dp_dig_pixel_rate_div_policy(dc, &param->timing)) {
327			/*this logic should be the same in get_pixel_clock_parameters() */
328			n_multiply = 1;
329			pix_per_cycle = 1;
330		}
331		/* M / N = Fstream / Flink
332		 * m_vid / n_vid = pixel rate / link rate
333		 */
334
335		m_vid_l *= param->timing.pix_clk_100hz / 10;
336		m_vid_l = div_u64(m_vid_l,
337			param->link_settings.link_rate
338				* LINK_RATE_REF_FREQ_IN_KHZ);
339
340		m_vid = (uint32_t) m_vid_l;
341
342		/* enable auto measurement */
343
344		REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0);
345
346		/* auto measurement need 1 full 0x8000 symbol cycle to kick in,
347		 * therefore program initial value for Mvid and Nvid
348		 */
349
350		REG_UPDATE(DP_VID_N, DP_VID_N, n_vid);
351
352		REG_UPDATE(DP_VID_M, DP_VID_M, m_vid);
353
354		REG_UPDATE_2(DP_VID_TIMING,
355				DP_VID_M_N_GEN_EN, 1,
356				DP_VID_N_MUL, n_multiply);
357
358		REG_UPDATE(DP_PIXEL_FORMAT,
359				DP_PIXEL_PER_CYCLE_PROCESSING_MODE,
360				pix_per_cycle);
361	}
362
363	/* make sure stream is disabled before resetting steer fifo */
364	REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, false);
365	REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 0, 10, 5000);
366
367	/* DIG_START is removed from the register spec */
368
369	/* switch DP encoder to CRTC data, but reset it the fifo first. It may happen
370	 * that it overflows during mode transition, and sometimes doesn't recover.
371	 */
372	REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1);
373	udelay(10);
374
375	REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0);
376
377	/* wait 100us for DIG/DP logic to prime
378	 * (i.e. a few video lines)
379	 */
380	udelay(100);
381
382	/* the hardware would start sending video at the start of the next DP
383	 * frame (i.e. rising edge of the vblank).
384	 * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this
385	 * register has no effect on enable transition! HW always makes sure
386	 * VID_STREAM enable at start of next frame, and this is not
387	 * programmable
388	 */
389
390	REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true);
391
392	/*
393	 * DIG Resync FIFO now needs to be explicitly enabled.
394	 * This should come after DP_VID_STREAM_ENABLE per HW docs.
395	 */
396	enc314_enable_fifo(enc);
397
398	link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM);
399}
400
401static void enc35_stream_encoder_map_to_link(
402		struct stream_encoder *enc,
403		uint32_t stream_enc_inst,
404		uint32_t link_enc_inst)
405{
406	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
407
408	ASSERT(stream_enc_inst < 5 && link_enc_inst < 5);
409	REG_UPDATE(STREAM_MAPPER_CONTROL,
410				DIG_STREAM_LINK_TARGET, link_enc_inst);
411}
412
413static void enc35_reset_fifo(struct stream_encoder *enc, bool reset)
414{
415	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
416	uint32_t reset_val = reset ? 1 : 0;
417	uint32_t is_symclk_on;
418
419	REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, reset_val);
420	REG_GET(DIG_FE_CLK_CNTL, DIG_FE_SYMCLK_FE_G_CLOCK_ON, &is_symclk_on);
421
422	if (is_symclk_on)
423		REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, reset_val, 10, 5000);
424	else
425		udelay(10);
426}
427
428static void enc35_disable_fifo(struct stream_encoder *enc)
429{
430	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
431
432	REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 0);
433	REG_UPDATE(DIG_FE_EN_CNTL, DIG_FE_ENABLE, 0);
434	REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, 0);
435}
436
437static void enc35_enable_fifo(struct stream_encoder *enc)
438{
439	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
440
441	REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, 0x7);
442	REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, 1);
443	REG_UPDATE(DIG_FE_EN_CNTL, DIG_FE_ENABLE, 1);
444
445	enc35_reset_fifo(enc, true);
446	enc35_reset_fifo(enc, false);
447
448	REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 1);
449}
450
451static const struct stream_encoder_funcs dcn35_str_enc_funcs = {
452	.dp_set_odm_combine =
453		enc314_dp_set_odm_combine,
454	.dp_set_stream_attribute =
455		enc2_stream_encoder_dp_set_stream_attribute,
456	.hdmi_set_stream_attribute =
457		enc35_stream_encoder_hdmi_set_stream_attribute,
458	.dvi_set_stream_attribute =
459		enc35_stream_encoder_dvi_set_stream_attribute,
460	.set_throttled_vcp_size =
461		enc1_stream_encoder_set_throttled_vcp_size,
462	.update_hdmi_info_packets =
463		enc3_stream_encoder_update_hdmi_info_packets,
464	.stop_hdmi_info_packets =
465		enc3_stream_encoder_stop_hdmi_info_packets,
466	.update_dp_info_packets_sdp_line_num =
467		enc3_stream_encoder_update_dp_info_packets_sdp_line_num,
468	.update_dp_info_packets =
469		enc3_stream_encoder_update_dp_info_packets,
470	.stop_dp_info_packets =
471		enc1_stream_encoder_stop_dp_info_packets,
472	.dp_blank =
473		enc314_stream_encoder_dp_blank,
474	.dp_unblank =
475		enc35_stream_encoder_dp_unblank,
476	.audio_mute_control = enc3_audio_mute_control,
477
478	.dp_audio_setup = enc3_se_dp_audio_setup,
479	.dp_audio_enable = enc3_se_dp_audio_enable,
480	.dp_audio_disable = enc1_se_dp_audio_disable,
481
482	.hdmi_audio_setup = enc3_se_hdmi_audio_setup,
483	.hdmi_audio_disable = enc1_se_hdmi_audio_disable,
484	.setup_stereo_sync  = enc1_setup_stereo_sync,
485	.set_avmute = enc1_stream_encoder_set_avmute,
486	.dig_connect_to_otg = enc1_dig_connect_to_otg,
487	.dig_source_otg = enc1_dig_source_otg,
488
489	.dp_get_pixel_format  = enc1_stream_encoder_dp_get_pixel_format,
490
491	.enc_read_state = enc314_read_state,
492	.dp_set_dsc_config = enc314_dp_set_dsc_config,
493	.dp_set_dsc_pps_info_packet = enc3_dp_set_dsc_pps_info_packet,
494	.set_dynamic_metadata = enc2_set_dynamic_metadata,
495	.hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute,
496	.dig_stream_enable = enc35_stream_encoder_enable,
497
498	.set_input_mode = enc314_set_dig_input_mode,
499	.enable_fifo = enc35_enable_fifo,
500	.disable_fifo = enc35_disable_fifo,
501	.map_stream_to_link = enc35_stream_encoder_map_to_link,
502};
503
504void dcn35_dio_stream_encoder_construct(
505	struct dcn10_stream_encoder *enc1,
506	struct dc_context *ctx,
507	struct dc_bios *bp,
508	enum engine_id eng_id,
509	struct vpg *vpg,
510	struct afmt *afmt,
511	const struct dcn10_stream_enc_registers *regs,
512	const struct dcn10_stream_encoder_shift *se_shift,
513	const struct dcn10_stream_encoder_mask *se_mask)
514{
515	enc1->base.funcs = &dcn35_str_enc_funcs;
516	enc1->base.ctx = ctx;
517	enc1->base.id = eng_id;
518	enc1->base.bp = bp;
519	enc1->base.vpg = vpg;
520	enc1->base.afmt = afmt;
521	enc1->regs = regs;
522	enc1->se_shift = se_shift;
523	enc1->se_mask = se_mask;
524	enc1->base.stream_enc_inst = vpg->inst;
525}
526
527