Commit e03868ec authored by Reza Amini's avatar Reza Amini Committed by Alex Deucher
Browse files

drm/amd/display: Fix VTEM InfoPacket programming



Refactor setting bit fields. Correcting the offset of MD0.
Initializing the InfoPacket header fields. Defining the field offsets
and masks.

Signed-off-by: default avatarReza Amini <Reza.Amini@amd.com>
Reviewed-by: default avatarAnthony Koo <Anthony.Koo@amd.com>
Acked-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 66acd441
Loading
Loading
Loading
Loading
+111 −33
Original line number Diff line number Diff line
@@ -50,6 +50,93 @@ struct core_freesync {
	struct dc *dc;
};

void setFieldWithMask(unsigned char *dest, unsigned int mask, unsigned int value)
{
	unsigned int shift = 0;

	if (!mask || !dest)
		return;

	while (!((mask >> shift) & 1))
		shift++;

	//reset
	*dest = *dest & ~mask;
	//set
	//dont let value span past mask
	value = value & (mask >> shift);
	//insert value
	*dest = *dest | (value << shift);
}

// VTEM Byte Offset
#define VRR_VTEM_PB0		0
#define VRR_VTEM_PB1		1
#define VRR_VTEM_PB2		2
#define VRR_VTEM_PB3		3
#define VRR_VTEM_PB4		4
#define VRR_VTEM_PB5		5
#define VRR_VTEM_PB6		6

#define VRR_VTEM_MD0		7
#define VRR_VTEM_MD1		8
#define VRR_VTEM_MD2		9
#define VRR_VTEM_MD3		10


// VTEM Byte Masks
//PB0
#define MASK__VRR_VTEM_PB0__RESERVED0  0x01
#define MASK__VRR_VTEM_PB0__SYNC       0x02
#define MASK__VRR_VTEM_PB0__VFR        0x04
#define MASK__VRR_VTEM_PB0__AFR        0x08
#define MASK__VRR_VTEM_PB0__DS_TYPE    0x30
	//0: Periodic pseudo-static EM Data Set
	//1: Periodic dynamic EM Data Set
	//2: Unique EM Data Set
	//3: Reserved
#define MASK__VRR_VTEM_PB0__END        0x40
#define MASK__VRR_VTEM_PB0__NEW        0x80

//PB1
#define MASK__VRR_VTEM_PB1__RESERVED1 0xFF

//PB2
#define MASK__VRR_VTEM_PB2__ORGANIZATION_ID 0xFF
	//0: This is a Vendor Specific EM Data Set
	//1: This EM Data Set is defined by This Specification (HDMI 2.1 r102.clean)
	//2: This EM Data Set is defined by CTA-861-G
	//3: This EM Data Set is defined by VESA
//PB3
#define MASK__VRR_VTEM_PB3__DATA_SET_TAG_MSB    0xFF
//PB4
#define MASK__VRR_VTEM_PB4__DATA_SET_TAG_LSB    0xFF
//PB5
#define MASK__VRR_VTEM_PB5__DATA_SET_LENGTH_MSB 0xFF
//PB6
#define MASK__VRR_VTEM_PB6__DATA_SET_LENGTH_LSB 0xFF



//PB7-27 (20 bytes):
//PB7 = MD0
#define MASK__VRR_VTEM_MD0__VRR_EN         0x01
#define MASK__VRR_VTEM_MD0__M_CONST        0x02
#define MASK__VRR_VTEM_MD0__RESERVED2      0x0C
#define MASK__VRR_VTEM_MD0__FVA_FACTOR_M1  0xF0

//MD1
#define MASK__VRR_VTEM_MD1__BASE_VFRONT    0xFF

//MD2
#define MASK__VRR_VTEM_MD2__BASE_REFRESH_RATE_98  0x03
#define MASK__VRR_VTEM_MD2__RB                    0x04
#define MASK__VRR_VTEM_MD2__RESERVED3             0xF8

//MD3
#define MASK__VRR_VTEM_MD3__BASE_REFRESH_RATE_07  0xFF


#define MOD_FREESYNC_TO_CORE(mod_freesync)\
		container_of(mod_freesync, struct core_freesync, public)

@@ -489,16 +576,14 @@ static void build_vrr_infopacket_header_vtem(enum signal_type signal,
	// HB0, HB1, HB2 indicates PacketType VTEMPacket
	infopacket->hb0 = 0x7F;
	infopacket->hb1 = 0xC0;
	infopacket->hb2 = 0x00;
	/* HB3 Bit Fields
	 * Reserved :1 = 0
	 * Sync     :1 = 0
	 * VFR      :1 = 1
	 * Ds_Type  :2 = 0
	 * End      :1 = 0
	 * New      :1 = 0
	 */
	infopacket->hb3 = 0x20;
	infopacket->hb2 = 0x00; //sequence_index

	setFieldWithMask(&infopacket->sb[VRR_VTEM_PB0], MASK__VRR_VTEM_PB0__VFR, 1);
	setFieldWithMask(&infopacket->sb[VRR_VTEM_PB2], MASK__VRR_VTEM_PB2__ORGANIZATION_ID, 1);
	setFieldWithMask(&infopacket->sb[VRR_VTEM_PB3], MASK__VRR_VTEM_PB3__DATA_SET_TAG_MSB, 0);
	setFieldWithMask(&infopacket->sb[VRR_VTEM_PB4], MASK__VRR_VTEM_PB4__DATA_SET_TAG_LSB, 1);
	setFieldWithMask(&infopacket->sb[VRR_VTEM_PB5], MASK__VRR_VTEM_PB5__DATA_SET_LENGTH_MSB, 0);
	setFieldWithMask(&infopacket->sb[VRR_VTEM_PB6], MASK__VRR_VTEM_PB6__DATA_SET_LENGTH_LSB, 4);
}

static void build_vrr_infopacket_header_v1(enum signal_type signal,
@@ -603,45 +688,36 @@ static void build_vrr_vtem_infopacket_data(const struct dc_stream_state *stream,
		const struct mod_vrr_params *vrr,
		struct dc_info_packet *infopacket)
{
	/* dc_info_packet to VtemPacket Translation of Bit-fields,
	 * SB[6]
	 * unsigned char VRR_EN        :1
	 * unsigned char M_CONST       :1
	 * unsigned char Reserved2     :2
	 * unsigned char FVA_Factor_M1 :4
	 * SB[7]
	 * unsigned char Base_Vfront   :8
	 * SB[8]
	 * unsigned char Base_Refresh_Rate_98 :2
	 * unsigned char RB                   :1
	 * unsigned char Reserved3            :5
	 * SB[9]
	 * unsigned char Base_RefreshRate_07  :8
	 */
	unsigned int fieldRateInHz;

	if (vrr->state == VRR_STATE_ACTIVE_VARIABLE ||
				vrr->state == VRR_STATE_ACTIVE_FIXED) {
		infopacket->sb[6] |= 0x01; //VRR_EN Bit = 1
		setFieldWithMask(&infopacket->sb[VRR_VTEM_MD0], MASK__VRR_VTEM_MD0__VRR_EN, 1);
	} else {
		infopacket->sb[6] &= 0xFE; //VRR_EN Bit = 0
		setFieldWithMask(&infopacket->sb[VRR_VTEM_MD0], MASK__VRR_VTEM_MD0__VRR_EN, 0);
	}

	if (!stream->timing.vic) {
		infopacket->sb[7] = stream->timing.v_front_porch;
		setFieldWithMask(&infopacket->sb[VRR_VTEM_MD1], MASK__VRR_VTEM_MD1__BASE_VFRONT,
				stream->timing.v_front_porch);


		/* TODO: In dal2, we check mode flags for a reduced blanking timing.
		 * Need a way to relay that information to this function.
		 * if("ReducedBlanking")
		 * {
		 *   infopacket->sb[8] |= 0x20; //Set 3rd bit to 1
		 *   setFieldWithMask(&infopacket->sb[VRR_VTEM_MD2], MASK__VRR_VTEM_MD2__RB, 1;
		 * }
		 */

		//TODO: DAL2 does FixPoint and rounding. Here we might need to account for that
		fieldRateInHz = (stream->timing.pix_clk_100hz * 100)/
			(stream->timing.h_total * stream->timing.v_total);

		infopacket->sb[8] |= ((fieldRateInHz & 0x300) >> 2);
		infopacket->sb[9] |= fieldRateInHz & 0xFF;
		setFieldWithMask(&infopacket->sb[VRR_VTEM_MD2],  MASK__VRR_VTEM_MD2__BASE_REFRESH_RATE_98,
				fieldRateInHz >> 8);
		setFieldWithMask(&infopacket->sb[VRR_VTEM_MD3], MASK__VRR_VTEM_MD3__BASE_REFRESH_RATE_07,
				fieldRateInHz);

	}
	infopacket->valid = true;
@@ -765,6 +841,8 @@ static void build_vrr_infopacket_vtem(const struct dc_stream_state *stream,
{
	//VTEM info packet for HdmiVrr

	memset(infopacket, 0, sizeof(struct dc_info_packet));

	//VTEM Packet is structured differently
	build_vrr_infopacket_header_vtem(stream->signal, infopacket);
	build_vrr_vtem_infopacket_data(stream, vrr, infopacket);