Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a3b08294 authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie
Browse files

drm/radeon/kms: make atombios_dig_transmitter_setup() version based



Use the table version to determine which params to use.

Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 58cdcb8b
Loading
Loading
Loading
Loading
+221 −122
Original line number Original line Diff line number Diff line
@@ -772,6 +772,11 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
		igp_lane_info = dig_connector->igp_lane_info;
		igp_lane_info = dig_connector->igp_lane_info;
	}
	}


	if (encoder->crtc) {
		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
		pll_id = radeon_crtc->pll_id;
	}

	/* no dig encoder assigned */
	/* no dig encoder assigned */
	if (dig_encoder == -1)
	if (dig_encoder == -1)
		return;
		return;
@@ -798,6 +803,10 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
		return;
		return;


	switch (frev) {
	case 1:
		switch (crev) {
		case 1:
			args.v1.ucAction = action;
			args.v1.ucAction = action;
			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
				args.v1.usInitInfo = cpu_to_le16(connector_object_id);
				args.v1.usInitInfo = cpu_to_le16(connector_object_id);
@@ -813,7 +822,107 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
				else
				else
					args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
					args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
			}
			}
	if (ASIC_IS_DCE4(rdev)) {

			args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;

			if (dig_encoder)
				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
			else
				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;

			if ((rdev->flags & RADEON_IS_IGP) &&
			    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
				if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
					if (igp_lane_info & 0x1)
						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
					else if (igp_lane_info & 0x2)
						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
					else if (igp_lane_info & 0x4)
						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
					else if (igp_lane_info & 0x8)
						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
				} else {
					if (igp_lane_info & 0x3)
						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
					else if (igp_lane_info & 0xc)
						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
				}
			}

			if (dig->linkb)
				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
			else
				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;

			if (is_dp)
				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
				if (dig->coherent_mode)
					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
				if (radeon_encoder->pixel_clock > 165000)
					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
			}
			break;
		case 2:
			args.v2.ucAction = action;
			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
				args.v2.usInitInfo = cpu_to_le16(connector_object_id);
			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
				args.v2.asMode.ucLaneSel = lane_num;
				args.v2.asMode.ucLaneSet = lane_set;
			} else {
				if (is_dp)
					args.v2.usPixelClock =
						cpu_to_le16(dp_clock / 10);
				else if (radeon_encoder->pixel_clock > 165000)
					args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
				else
					args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
			}

			args.v2.acConfig.ucEncoderSel = dig_encoder;
			if (dig->linkb)
				args.v2.acConfig.ucLinkSel = 1;

			switch (radeon_encoder->encoder_id) {
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
				args.v2.acConfig.ucTransmitterSel = 0;
				break;
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
				args.v2.acConfig.ucTransmitterSel = 1;
				break;
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
				args.v2.acConfig.ucTransmitterSel = 2;
				break;
			}

			if (is_dp) {
				args.v2.acConfig.fCoherentMode = 1;
				args.v2.acConfig.fDPConnector = 1;
			} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
				if (dig->coherent_mode)
					args.v2.acConfig.fCoherentMode = 1;
				if (radeon_encoder->pixel_clock > 165000)
					args.v2.acConfig.fDualLinkConnector = 1;
			}
			break;
		case 3:
			args.v3.ucAction = action;
			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
				args.v3.usInitInfo = cpu_to_le16(connector_object_id);
			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
				args.v3.asMode.ucLaneSel = lane_num;
				args.v3.asMode.ucLaneSet = lane_set;
			} else {
				if (is_dp)
					args.v3.usPixelClock =
						cpu_to_le16(dp_clock / 10);
				else if (radeon_encoder->pixel_clock > 165000)
					args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
				else
					args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
			}

			if (is_dp)
			if (is_dp)
				args.v3.ucLaneNum = dp_lane_count;
				args.v3.ucLaneNum = dp_lane_count;
			else if (radeon_encoder->pixel_clock > 165000)
			else if (radeon_encoder->pixel_clock > 165000)
@@ -830,27 +939,11 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
			 * DP PHY should be clocked from external src if there is
			 * DP PHY should be clocked from external src if there is
			 * one.
			 * one.
			 */
			 */
		if (encoder->crtc) {
			struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
			pll_id = radeon_crtc->pll_id;
		}

		if (ASIC_IS_DCE5(rdev)) {
			/* On DCE5 DCPLL usually generates the DP ref clock */
			if (is_dp) {
				if (rdev->clock.dp_extclk)
					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
				else
					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
			} else
				args.v4.acConfig.ucRefClkSource = pll_id;
		} else {
			/* On DCE4, if there is an external clock, it generates the DP ref clock */
			/* On DCE4, if there is an external clock, it generates the DP ref clock */
			if (is_dp && rdev->clock.dp_extclk)
			if (is_dp && rdev->clock.dp_extclk)
				args.v3.acConfig.ucRefClkSource = 2; /* external src */
				args.v3.acConfig.ucRefClkSource = 2; /* external src */
			else
			else
				args.v3.acConfig.ucRefClkSource = pll_id;
				args.v3.acConfig.ucRefClkSource = pll_id;
		}


			switch (radeon_encoder->encoder_id) {
			switch (radeon_encoder->encoder_id) {
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
@@ -872,72 +965,78 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
				if (radeon_encoder->pixel_clock > 165000)
				if (radeon_encoder->pixel_clock > 165000)
					args.v3.acConfig.fDualLinkConnector = 1;
					args.v3.acConfig.fDualLinkConnector = 1;
			}
			}
	} else if (ASIC_IS_DCE32(rdev)) {
			break;
		args.v2.acConfig.ucEncoderSel = dig_encoder;
		case 4:
			args.v4.ucAction = action;
			if (action == ATOM_TRANSMITTER_ACTION_INIT) {
				args.v4.usInitInfo = cpu_to_le16(connector_object_id);
			} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
				args.v4.asMode.ucLaneSel = lane_num;
				args.v4.asMode.ucLaneSet = lane_set;
			} else {
				if (is_dp)
					args.v4.usPixelClock =
						cpu_to_le16(dp_clock / 10);
				else if (radeon_encoder->pixel_clock > 165000)
					args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
				else
					args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
			}

			if (is_dp)
				args.v4.ucLaneNum = dp_lane_count;
			else if (radeon_encoder->pixel_clock > 165000)
				args.v4.ucLaneNum = 8;
			else
				args.v4.ucLaneNum = 4;

			if (dig->linkb)
			if (dig->linkb)
			args.v2.acConfig.ucLinkSel = 1;
				args.v4.acConfig.ucLinkSel = 1;
			if (dig_encoder & 1)
				args.v4.acConfig.ucEncoderSel = 1;

			/* Select the PLL for the PHY
			 * DP PHY should be clocked from external src if there is
			 * one.
			 */
			/* On DCE5 DCPLL usually generates the DP ref clock */
			if (is_dp) {
				if (rdev->clock.dp_extclk)
					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
				else
					args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
			} else
				args.v4.acConfig.ucRefClkSource = pll_id;


			switch (radeon_encoder->encoder_id) {
			switch (radeon_encoder->encoder_id) {
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
			args.v2.acConfig.ucTransmitterSel = 0;
				args.v4.acConfig.ucTransmitterSel = 0;
				break;
				break;
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
			args.v2.acConfig.ucTransmitterSel = 1;
				args.v4.acConfig.ucTransmitterSel = 1;
				break;
				break;
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
			args.v2.acConfig.ucTransmitterSel = 2;
				args.v4.acConfig.ucTransmitterSel = 2;
				break;
				break;
			}
			}


		if (is_dp) {
			args.v2.acConfig.fCoherentMode = 1;
			args.v2.acConfig.fDPConnector = 1;
		} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
			if (dig->coherent_mode)
				args.v2.acConfig.fCoherentMode = 1;
			if (radeon_encoder->pixel_clock > 165000)
				args.v2.acConfig.fDualLinkConnector = 1;
		}
	} else {
		args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;

		if (dig_encoder)
			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
		else
			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;

		if ((rdev->flags & RADEON_IS_IGP) &&
		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
			if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
				if (igp_lane_info & 0x1)
					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
				else if (igp_lane_info & 0x2)
					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
				else if (igp_lane_info & 0x4)
					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
				else if (igp_lane_info & 0x8)
					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
			} else {
				if (igp_lane_info & 0x3)
					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
				else if (igp_lane_info & 0xc)
					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
			}
		}

		if (dig->linkb)
			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
		else
			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;

			if (is_dp)
			if (is_dp)
			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
				args.v4.acConfig.fCoherentMode = 1; /* DP requires coherent */
			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
			else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
				if (dig->coherent_mode)
				if (dig->coherent_mode)
				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
					args.v4.acConfig.fCoherentMode = 1;
				if (radeon_encoder->pixel_clock > 165000)
				if (radeon_encoder->pixel_clock > 165000)
				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
					args.v4.acConfig.fDualLinkConnector = 1;
			}
			}
			break;
		default:
			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
			break;
		}
		break;
	default:
		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
		break;
	}
	}


	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);