cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dcn20_stream_encoder.c (19608B)


      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 <linux/delay.h>
     27
     28#include "dc_bios_types.h"
     29#include "dcn20_stream_encoder.h"
     30#include "reg_helper.h"
     31#include "hw_shared.h"
     32#include "inc/link_dpcd.h"
     33#include "dpcd_defs.h"
     34
     35#define DC_LOGGER \
     36		enc1->base.ctx->logger
     37
     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
     47#define CTX \
     48	enc1->base.ctx
     49
     50
     51static void enc2_update_hdmi_info_packet(
     52	struct dcn10_stream_encoder *enc1,
     53	uint32_t packet_index,
     54	const struct dc_info_packet *info_packet)
     55{
     56	uint32_t cont, send, line;
     57
     58	if (info_packet->valid) {
     59		enc1_update_generic_info_packet(
     60			enc1,
     61			packet_index,
     62			info_packet);
     63
     64		/* enable transmission of packet(s) -
     65		 * packet transmission begins on the next frame */
     66		cont = 1;
     67		/* send packet(s) every frame */
     68		send = 1;
     69		/* select line number to send packets on */
     70		line = 2;
     71	} else {
     72		cont = 0;
     73		send = 0;
     74		line = 0;
     75	}
     76
     77	/* DP_SEC_GSP[x]_LINE_REFERENCE - keep default value REFER_TO_DP_SOF */
     78
     79	/* choose which generic packet control to use */
     80	switch (packet_index) {
     81	case 0:
     82		REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0,
     83				HDMI_GENERIC0_CONT, cont,
     84				HDMI_GENERIC0_SEND, send);
     85		REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1,
     86				HDMI_GENERIC0_LINE, line);
     87		break;
     88	case 1:
     89		REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0,
     90				HDMI_GENERIC1_CONT, cont,
     91				HDMI_GENERIC1_SEND, send);
     92		REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1,
     93				HDMI_GENERIC1_LINE, line);
     94		break;
     95	case 2:
     96		REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0,
     97				HDMI_GENERIC2_CONT, cont,
     98				HDMI_GENERIC2_SEND, send);
     99		REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2,
    100				HDMI_GENERIC2_LINE, line);
    101		break;
    102	case 3:
    103		REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0,
    104				HDMI_GENERIC3_CONT, cont,
    105				HDMI_GENERIC3_SEND, send);
    106		REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2,
    107				HDMI_GENERIC3_LINE, line);
    108		break;
    109	case 4:
    110		REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0,
    111				HDMI_GENERIC4_CONT, cont,
    112				HDMI_GENERIC4_SEND, send);
    113		REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3,
    114				HDMI_GENERIC4_LINE, line);
    115		break;
    116	case 5:
    117		REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0,
    118				HDMI_GENERIC5_CONT, cont,
    119				HDMI_GENERIC5_SEND, send);
    120		REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3,
    121				HDMI_GENERIC5_LINE, line);
    122		break;
    123	case 6:
    124		REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0,
    125				HDMI_GENERIC6_CONT, cont,
    126				HDMI_GENERIC6_SEND, send);
    127		REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4,
    128				HDMI_GENERIC6_LINE, line);
    129		break;
    130	case 7:
    131		REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0,
    132				HDMI_GENERIC7_CONT, cont,
    133				HDMI_GENERIC7_SEND, send);
    134		REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4,
    135				HDMI_GENERIC7_LINE, line);
    136		break;
    137	default:
    138		/* invalid HW packet index */
    139		DC_LOG_WARNING(
    140			"Invalid HW packet index: %s()\n",
    141			__func__);
    142		return;
    143	}
    144}
    145
    146static void enc2_stream_encoder_update_hdmi_info_packets(
    147	struct stream_encoder *enc,
    148	const struct encoder_info_frame *info_frame)
    149{
    150	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
    151
    152	/* for bring up, disable dp double  TODO */
    153	REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1);
    154
    155	/*Always add mandatory packets first followed by optional ones*/
    156	enc2_update_hdmi_info_packet(enc1, 0, &info_frame->avi);
    157	enc2_update_hdmi_info_packet(enc1, 1, &info_frame->hfvsif);
    158	enc2_update_hdmi_info_packet(enc1, 2, &info_frame->gamut);
    159	enc2_update_hdmi_info_packet(enc1, 3, &info_frame->vendor);
    160	enc2_update_hdmi_info_packet(enc1, 4, &info_frame->spd);
    161	enc2_update_hdmi_info_packet(enc1, 5, &info_frame->hdrsmd);
    162}
    163
    164static void enc2_stream_encoder_stop_hdmi_info_packets(
    165	struct stream_encoder *enc)
    166{
    167	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
    168
    169	/* stop generic packets 0,1 on HDMI */
    170	REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0,
    171		HDMI_GENERIC0_CONT, 0,
    172		HDMI_GENERIC0_SEND, 0,
    173		HDMI_GENERIC1_CONT, 0,
    174		HDMI_GENERIC1_SEND, 0);
    175	REG_SET_2(HDMI_GENERIC_PACKET_CONTROL1, 0,
    176		HDMI_GENERIC0_LINE, 0,
    177		HDMI_GENERIC1_LINE, 0);
    178
    179	/* stop generic packets 2,3 on HDMI */
    180	REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0,
    181		HDMI_GENERIC2_CONT, 0,
    182		HDMI_GENERIC2_SEND, 0,
    183		HDMI_GENERIC3_CONT, 0,
    184		HDMI_GENERIC3_SEND, 0);
    185	REG_SET_2(HDMI_GENERIC_PACKET_CONTROL2, 0,
    186		HDMI_GENERIC2_LINE, 0,
    187		HDMI_GENERIC3_LINE, 0);
    188
    189	/* stop generic packets 4,5 on HDMI */
    190	REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0,
    191		HDMI_GENERIC4_CONT, 0,
    192		HDMI_GENERIC4_SEND, 0,
    193		HDMI_GENERIC5_CONT, 0,
    194		HDMI_GENERIC5_SEND, 0);
    195	REG_SET_2(HDMI_GENERIC_PACKET_CONTROL3, 0,
    196		HDMI_GENERIC4_LINE, 0,
    197		HDMI_GENERIC5_LINE, 0);
    198
    199	/* stop generic packets 6,7 on HDMI */
    200	REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0,
    201		HDMI_GENERIC6_CONT, 0,
    202		HDMI_GENERIC6_SEND, 0,
    203		HDMI_GENERIC7_CONT, 0,
    204		HDMI_GENERIC7_SEND, 0);
    205	REG_SET_2(HDMI_GENERIC_PACKET_CONTROL4, 0,
    206		HDMI_GENERIC6_LINE, 0,
    207		HDMI_GENERIC7_LINE, 0);
    208}
    209
    210
    211/* Update GSP7 SDP 128 byte long */
    212static void enc2_update_gsp7_128_info_packet(
    213	struct dcn10_stream_encoder *enc1,
    214	const struct dc_info_packet_128 *info_packet,
    215	bool immediate_update)
    216{
    217	uint32_t i;
    218
    219	/* TODOFPGA Figure out a proper number for max_retries polling for lock
    220	 * use 50 for now.
    221	 */
    222	uint32_t max_retries = 50;
    223	const uint32_t *content = (const uint32_t *) &info_packet->sb[0];
    224
    225	ASSERT(info_packet->hb1  == DC_DP_INFOFRAME_TYPE_PPS);
    226
    227	/* Configure for PPS packet size (128 bytes) */
    228	REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP7_PPS, 1);
    229
    230	/* We need turn on clock before programming AFMT block*/
    231	REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1);
    232
    233	/* Poll dig_update_lock is not locked -> asic internal signal
    234	 * assumes otg master lock will unlock it
    235	 */
    236	/*REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, 0, 10, max_retries);*/
    237
    238	/* Wait for HW/SW GSP memory access conflict to go away */
    239	REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT,
    240			0, 10, max_retries);
    241
    242	/* Clear HW/SW memory access conflict flag */
    243	REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1);
    244
    245	/* write generic packet header */
    246	REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, 7);
    247	REG_SET_4(AFMT_GENERIC_HDR, 0,
    248			AFMT_GENERIC_HB0, info_packet->hb0,
    249			AFMT_GENERIC_HB1, info_packet->hb1,
    250			AFMT_GENERIC_HB2, info_packet->hb2,
    251			AFMT_GENERIC_HB3, info_packet->hb3);
    252
    253	/* Write generic packet content 128 bytes long. Four sets are used (indexes 7
    254	 * through 10) to fit 128 bytes.
    255	 */
    256	for (i = 0; i < 4; i++) {
    257		uint32_t packet_index = 7 + i;
    258		REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, packet_index);
    259
    260		REG_WRITE(AFMT_GENERIC_0, *content++);
    261		REG_WRITE(AFMT_GENERIC_1, *content++);
    262		REG_WRITE(AFMT_GENERIC_2, *content++);
    263		REG_WRITE(AFMT_GENERIC_3, *content++);
    264		REG_WRITE(AFMT_GENERIC_4, *content++);
    265		REG_WRITE(AFMT_GENERIC_5, *content++);
    266		REG_WRITE(AFMT_GENERIC_6, *content++);
    267		REG_WRITE(AFMT_GENERIC_7, *content++);
    268	}
    269
    270	REG_UPDATE_2(AFMT_VBI_PACKET_CONTROL1,
    271			AFMT_GENERIC7_FRAME_UPDATE, !immediate_update,
    272			AFMT_GENERIC7_IMMEDIATE_UPDATE, immediate_update);
    273}
    274
    275/* Set DSC-related configuration.
    276 *   dsc_mode: 0 disables DSC, other values enable DSC in specified format
    277 *   sc_bytes_per_pixel: Bytes per pixel in u3.28 format
    278 *   dsc_slice_width: Slice width in pixels
    279 */
    280static void enc2_dp_set_dsc_config(struct stream_encoder *enc,
    281					enum optc_dsc_mode dsc_mode,
    282					uint32_t dsc_bytes_per_pixel,
    283					uint32_t dsc_slice_width)
    284{
    285	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
    286
    287	REG_UPDATE_2(DP_DSC_CNTL,
    288			DP_DSC_MODE, dsc_mode,
    289			DP_DSC_SLICE_WIDTH, dsc_slice_width);
    290
    291	REG_SET(DP_DSC_BYTES_PER_PIXEL, 0,
    292		DP_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel);
    293}
    294
    295
    296static void enc2_dp_set_dsc_pps_info_packet(struct stream_encoder *enc,
    297					bool enable,
    298					uint8_t *dsc_packed_pps,
    299					bool immediate_update)
    300{
    301	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
    302
    303	if (enable) {
    304		struct dc_info_packet_128 pps_sdp;
    305
    306		ASSERT(dsc_packed_pps);
    307
    308		/* Load PPS into infoframe (SDP) registers */
    309		pps_sdp.valid = true;
    310		pps_sdp.hb0 = 0;
    311		pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS;
    312		pps_sdp.hb2 = 127;
    313		pps_sdp.hb3 = 0;
    314		memcpy(&pps_sdp.sb[0], dsc_packed_pps, sizeof(pps_sdp.sb));
    315		enc2_update_gsp7_128_info_packet(enc1, &pps_sdp, immediate_update);
    316
    317		/* Enable Generic Stream Packet 7 (GSP) transmission */
    318		//REG_UPDATE(DP_SEC_CNTL,
    319		//	DP_SEC_GSP7_ENABLE, 1);
    320
    321		/* SW should make sure VBID[6] update line number is bigger
    322		 * than PPS transmit line number
    323		 */
    324		REG_UPDATE(DP_SEC_CNTL6,
    325				DP_SEC_GSP7_LINE_NUM, 2);
    326		REG_UPDATE_2(DP_MSA_VBID_MISC,
    327				DP_VBID6_LINE_REFERENCE, 0,
    328				DP_VBID6_LINE_NUM, 3);
    329
    330		/* Send PPS data at the line number specified above.
    331		 * DP spec requires PPS to be sent only when it changes, however since
    332		 * decoder has to be able to handle its change on every frame, we're
    333		 * sending it always (i.e. on every frame) to reduce the chance it'd be
    334		 * missed by decoder. If it turns out required to send PPS only when it
    335		 * changes, we can use DP_SEC_GSP7_SEND register.
    336		 */
    337		REG_UPDATE_2(DP_SEC_CNTL,
    338			DP_SEC_GSP7_ENABLE, 1,
    339			DP_SEC_STREAM_ENABLE, 1);
    340	} else {
    341		/* Disable Generic Stream Packet 7 (GSP) transmission */
    342		REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, 0);
    343		REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP7_PPS, 0);
    344	}
    345}
    346
    347
    348/* this function read dsc related register fields to be logged later in dcn10_log_hw_state
    349 * into a dcn_dsc_state struct.
    350 */
    351static void enc2_read_state(struct stream_encoder *enc, struct enc_state *s)
    352{
    353	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
    354
    355	//if dsc is enabled, continue to read
    356	REG_GET(DP_DSC_CNTL, DP_DSC_MODE, &s->dsc_mode);
    357	if (s->dsc_mode) {
    358		REG_GET(DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, &s->dsc_slice_width);
    359		REG_GET(DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, &s->sec_gsp_pps_line_num);
    360
    361		REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, &s->vbid6_line_reference);
    362		REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, &s->vbid6_line_num);
    363
    364		REG_GET(DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, &s->sec_gsp_pps_enable);
    365		REG_GET(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, &s->sec_stream_enable);
    366	}
    367}
    368
    369/* Set Dynamic Metadata-configuration.
    370 *   enable_dme:         TRUE: enables Dynamic Metadata Enfine, FALSE: disables DME
    371 *   hubp_requestor_id:  HUBP physical instance that is the source of dynamic metadata
    372 *                       only needs to be set when enable_dme is TRUE
    373 *   dmdata_mode:        dynamic metadata packet type: DP, HDMI, or Dolby Vision
    374 *
    375 *   Ensure the OTG master update lock is set when changing DME configuration.
    376 */
    377void enc2_set_dynamic_metadata(struct stream_encoder *enc,
    378		bool enable_dme,
    379		uint32_t hubp_requestor_id,
    380		enum dynamic_metadata_mode dmdata_mode)
    381{
    382	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
    383
    384	if (enable_dme) {
    385		REG_UPDATE_2(DME_CONTROL,
    386				METADATA_HUBP_REQUESTOR_ID, hubp_requestor_id,
    387				METADATA_STREAM_TYPE, (dmdata_mode == dmdata_dolby_vision) ? 1 : 0);
    388
    389		/* Use default line reference DP_SOF for bringup.
    390		 * Should use OTG_SOF for DRR cases
    391		 */
    392		if (dmdata_mode == dmdata_dp)
    393			REG_UPDATE_3(DP_SEC_METADATA_TRANSMISSION,
    394					DP_SEC_METADATA_PACKET_ENABLE, 1,
    395					DP_SEC_METADATA_PACKET_LINE_REFERENCE, 0,
    396					DP_SEC_METADATA_PACKET_LINE, 20);
    397		else {
    398			REG_UPDATE_3(HDMI_METADATA_PACKET_CONTROL,
    399					HDMI_METADATA_PACKET_ENABLE, 1,
    400					HDMI_METADATA_PACKET_LINE_REFERENCE, 0,
    401					HDMI_METADATA_PACKET_LINE, 2);
    402
    403			if (dmdata_mode == dmdata_dolby_vision)
    404				REG_UPDATE(DIG_FE_CNTL,
    405						DOLBY_VISION_EN, 1);
    406		}
    407
    408		REG_UPDATE(DME_CONTROL,
    409				METADATA_ENGINE_EN, 1);
    410	} else {
    411		REG_UPDATE(DME_CONTROL,
    412				METADATA_ENGINE_EN, 0);
    413
    414		if (dmdata_mode == dmdata_dp)
    415			REG_UPDATE(DP_SEC_METADATA_TRANSMISSION,
    416					DP_SEC_METADATA_PACKET_ENABLE, 0);
    417		else {
    418			REG_UPDATE(HDMI_METADATA_PACKET_CONTROL,
    419					HDMI_METADATA_PACKET_ENABLE, 0);
    420			REG_UPDATE(DIG_FE_CNTL,
    421					DOLBY_VISION_EN, 0);
    422		}
    423	}
    424}
    425
    426static void enc2_stream_encoder_update_dp_info_packets(
    427	struct stream_encoder *enc,
    428	const struct encoder_info_frame *info_frame)
    429{
    430	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
    431	uint32_t dmdata_packet_enabled = 0;
    432
    433	enc1_stream_encoder_update_dp_info_packets(enc, info_frame);
    434
    435	/* check if dynamic metadata packet transmission is enabled */
    436	REG_GET(DP_SEC_METADATA_TRANSMISSION,
    437			DP_SEC_METADATA_PACKET_ENABLE, &dmdata_packet_enabled);
    438
    439	if (dmdata_packet_enabled)
    440		REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1);
    441}
    442
    443static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
    444{
    445	bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420;
    446
    447	two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
    448			&& !timing->dsc_cfg.ycbcr422_simple);
    449	return two_pix;
    450}
    451
    452void enc2_stream_encoder_dp_unblank(
    453		struct dc_link *link,
    454		struct stream_encoder *enc,
    455		const struct encoder_unblank_param *param)
    456{
    457	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
    458
    459	if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) {
    460		uint32_t n_vid = 0x8000;
    461		uint32_t m_vid;
    462		uint32_t n_multiply = 0;
    463		uint64_t m_vid_l = n_vid;
    464
    465		/* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */
    466		if (is_two_pixels_per_containter(&param->timing) || param->opp_cnt > 1) {
    467			/*this logic should be the same in get_pixel_clock_parameters() */
    468			n_multiply = 1;
    469		}
    470		/* M / N = Fstream / Flink
    471		 * m_vid / n_vid = pixel rate / link rate
    472		 */
    473
    474		m_vid_l *= param->timing.pix_clk_100hz / 10;
    475		m_vid_l = div_u64(m_vid_l,
    476			param->link_settings.link_rate
    477				* LINK_RATE_REF_FREQ_IN_KHZ);
    478
    479		m_vid = (uint32_t) m_vid_l;
    480
    481		/* enable auto measurement */
    482
    483		REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0);
    484
    485		/* auto measurement need 1 full 0x8000 symbol cycle to kick in,
    486		 * therefore program initial value for Mvid and Nvid
    487		 */
    488
    489		REG_UPDATE(DP_VID_N, DP_VID_N, n_vid);
    490
    491		REG_UPDATE(DP_VID_M, DP_VID_M, m_vid);
    492
    493		REG_UPDATE_2(DP_VID_TIMING,
    494				DP_VID_M_N_GEN_EN, 1,
    495				DP_VID_N_MUL, n_multiply);
    496	}
    497
    498	/* make sure stream is disabled before resetting steer fifo */
    499	REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, false);
    500	REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 0, 10, 5000);
    501
    502	/* set DIG_START to 0x1 to reset FIFO */
    503	REG_UPDATE(DIG_FE_CNTL, DIG_START, 1);
    504	udelay(1);
    505
    506	/* write 0 to take the FIFO out of reset */
    507
    508	REG_UPDATE(DIG_FE_CNTL, DIG_START, 0);
    509
    510	/* switch DP encoder to CRTC data, but reset it the fifo first. It may happen
    511	 * that it overflows during mode transition, and sometimes doesn't recover.
    512	 */
    513	REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1);
    514	udelay(10);
    515
    516	REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0);
    517
    518	/* wait 100us for DIG/DP logic to prime
    519	 * (i.e. a few video lines)
    520	 */
    521	udelay(100);
    522
    523	/* the hardware would start sending video at the start of the next DP
    524	 * frame (i.e. rising edge of the vblank).
    525	 * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this
    526	 * register has no effect on enable transition! HW always guarantees
    527	 * VID_STREAM enable at start of next frame, and this is not
    528	 * programmable
    529	 */
    530
    531	REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true);
    532
    533	dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM);
    534}
    535
    536static void enc2_dp_set_odm_combine(
    537	struct stream_encoder *enc,
    538	bool odm_combine)
    539{
    540	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
    541
    542	REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, odm_combine);
    543}
    544
    545void enc2_stream_encoder_dp_set_stream_attribute(
    546	struct stream_encoder *enc,
    547	struct dc_crtc_timing *crtc_timing,
    548	enum dc_color_space output_color_space,
    549	bool use_vsc_sdp_for_colorimetry,
    550	uint32_t enable_sdp_splitting)
    551{
    552	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
    553
    554	enc1_stream_encoder_dp_set_stream_attribute(enc,
    555			crtc_timing,
    556			output_color_space,
    557			use_vsc_sdp_for_colorimetry,
    558			enable_sdp_splitting);
    559
    560	REG_UPDATE(DP_SEC_FRAMING4,
    561		DP_SST_SDP_SPLITTING, enable_sdp_splitting);
    562}
    563
    564uint32_t enc2_get_fifo_cal_average_level(
    565		struct stream_encoder *enc)
    566{
    567	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
    568	uint32_t fifo_level;
    569
    570	REG_GET(DIG_FIFO_STATUS,
    571			DIG_FIFO_CAL_AVERAGE_LEVEL, &fifo_level);
    572	return fifo_level;
    573}
    574
    575static const struct stream_encoder_funcs dcn20_str_enc_funcs = {
    576	.dp_set_odm_combine =
    577		enc2_dp_set_odm_combine,
    578	.dp_set_stream_attribute =
    579		enc2_stream_encoder_dp_set_stream_attribute,
    580	.hdmi_set_stream_attribute =
    581		enc1_stream_encoder_hdmi_set_stream_attribute,
    582	.dvi_set_stream_attribute =
    583		enc1_stream_encoder_dvi_set_stream_attribute,
    584	.set_throttled_vcp_size =
    585		enc1_stream_encoder_set_throttled_vcp_size,
    586	.update_hdmi_info_packets =
    587		enc2_stream_encoder_update_hdmi_info_packets,
    588	.stop_hdmi_info_packets =
    589		enc2_stream_encoder_stop_hdmi_info_packets,
    590	.update_dp_info_packets =
    591		enc2_stream_encoder_update_dp_info_packets,
    592	.send_immediate_sdp_message =
    593		enc1_stream_encoder_send_immediate_sdp_message,
    594	.stop_dp_info_packets =
    595		enc1_stream_encoder_stop_dp_info_packets,
    596	.dp_blank =
    597		enc1_stream_encoder_dp_blank,
    598	.dp_unblank =
    599		enc2_stream_encoder_dp_unblank,
    600	.audio_mute_control = enc1_se_audio_mute_control,
    601
    602	.dp_audio_setup = enc1_se_dp_audio_setup,
    603	.dp_audio_enable = enc1_se_dp_audio_enable,
    604	.dp_audio_disable = enc1_se_dp_audio_disable,
    605
    606	.hdmi_audio_setup = enc1_se_hdmi_audio_setup,
    607	.hdmi_audio_disable = enc1_se_hdmi_audio_disable,
    608	.setup_stereo_sync  = enc1_setup_stereo_sync,
    609	.set_avmute = enc1_stream_encoder_set_avmute,
    610	.dig_connect_to_otg  = enc1_dig_connect_to_otg,
    611	.dig_source_otg = enc1_dig_source_otg,
    612
    613	.dp_get_pixel_format =
    614		enc1_stream_encoder_dp_get_pixel_format,
    615
    616	.enc_read_state = enc2_read_state,
    617	.dp_set_dsc_config = enc2_dp_set_dsc_config,
    618	.dp_set_dsc_pps_info_packet = enc2_dp_set_dsc_pps_info_packet,
    619	.set_dynamic_metadata = enc2_set_dynamic_metadata,
    620	.hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute,
    621	.get_fifo_cal_average_level = enc2_get_fifo_cal_average_level,
    622};
    623
    624void dcn20_stream_encoder_construct(
    625	struct dcn10_stream_encoder *enc1,
    626	struct dc_context *ctx,
    627	struct dc_bios *bp,
    628	enum engine_id eng_id,
    629	const struct dcn10_stream_enc_registers *regs,
    630	const struct dcn10_stream_encoder_shift *se_shift,
    631	const struct dcn10_stream_encoder_mask *se_mask)
    632{
    633	enc1->base.funcs = &dcn20_str_enc_funcs;
    634	enc1->base.ctx = ctx;
    635	enc1->base.id = eng_id;
    636	enc1->base.bp = bp;
    637	enc1->regs = regs;
    638	enc1->se_shift = se_shift;
    639	enc1->se_mask = se_mask;
    640	enc1->base.stream_enc_inst = eng_id - ENGINE_ID_DIGA;
    641}
    642