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

Commit 6f50e075 authored by Alex Deucher's avatar Alex Deucher Committed by Christian König
Browse files

drm/radeon/atom: rework encoder enable/disable sequence



This more closely matches what the vbios does and also
adds a quirk for travis lvds displays and powers down
the sink on DP displays which saves some power and may
fix display issues in some cases.

Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Acked-by: default avatarChristian König <christian.koenig@amd.com>
parent 2953da15
Loading
Loading
Loading
Loading
+34 −48
Original line number Original line Diff line number Diff line
@@ -1633,10 +1633,16 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
	struct radeon_connector *radeon_connector = NULL;
	struct radeon_connector *radeon_connector = NULL;
	struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
	struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
	bool travis_quirk = false;


	if (connector) {
	if (connector) {
		radeon_connector = to_radeon_connector(connector);
		radeon_connector = to_radeon_connector(connector);
		radeon_dig_connector = radeon_connector->con_priv;
		radeon_dig_connector = radeon_connector->con_priv;
		if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
		     ENCODER_OBJECT_ID_TRAVIS) &&
		    (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
		    !ASIC_IS_DCE5(rdev))
			travis_quirk = true;
	}
	}


	switch (mode) {
	switch (mode) {
@@ -1657,17 +1663,13 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
					atombios_external_encoder_setup(encoder, ext_encoder,
					atombios_external_encoder_setup(encoder, ext_encoder,
									EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
									EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
			}
			}
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
		} else if (ASIC_IS_DCE4(rdev)) {
		} else if (ASIC_IS_DCE4(rdev)) {
			/* setup and enable the encoder */
			/* setup and enable the encoder */
			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
			/* enable the transmitter */
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
		} else {
		} else {
			/* setup and enable the encoder and transmitter */
			/* setup and enable the encoder and transmitter */
			atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
			atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
		}
		}
		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
@@ -1675,68 +1677,56 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
							     ATOM_TRANSMITTER_ACTION_POWER_ON);
							     ATOM_TRANSMITTER_ACTION_POWER_ON);
				radeon_dig_connector->edp_on = true;
				radeon_dig_connector->edp_on = true;
			}
			}
		}
		/* enable the transmitter */
		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
			/* DP_SET_POWER_D0 is set in radeon_dp_link_train */
			radeon_dp_link_train(encoder, connector);
			radeon_dp_link_train(encoder, connector);
			if (ASIC_IS_DCE4(rdev))
			if (ASIC_IS_DCE4(rdev))
				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
		}
		}
		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
			atombios_dig_transmitter_setup(encoder,
						       ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
		if (ext_encoder)
			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
		break;
		break;
	case DRM_MODE_DPMS_STANDBY:
	case DRM_MODE_DPMS_STANDBY:
	case DRM_MODE_DPMS_SUSPEND:
	case DRM_MODE_DPMS_SUSPEND:
	case DRM_MODE_DPMS_OFF:
	case DRM_MODE_DPMS_OFF:
		if (ASIC_IS_DCE4(rdev)) {
			if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector)
				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
		}
		if (ext_encoder)
			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
			atombios_dig_transmitter_setup(encoder,
						       ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);

		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) &&
		    connector && !travis_quirk)
			radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
		if (ASIC_IS_DCE4(rdev)) {
		if (ASIC_IS_DCE4(rdev)) {
			/* disable the transmitter */
			/* disable the transmitter */
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
			atombios_dig_transmitter_setup(encoder,
						       ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
		} else {
		} else {
			/* disable the encoder and transmitter */
			/* disable the encoder and transmitter */
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
			atombios_dig_transmitter_setup(encoder,
						       ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
		}
		}
		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
			if (ASIC_IS_DCE4(rdev))
			if (travis_quirk)
				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
				radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
				atombios_set_edp_panel_power(connector,
				atombios_set_edp_panel_power(connector,
							     ATOM_TRANSMITTER_ACTION_POWER_OFF);
							     ATOM_TRANSMITTER_ACTION_POWER_OFF);
				radeon_dig_connector->edp_on = false;
				radeon_dig_connector->edp_on = false;
			}
			}
		}
		}
		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
		break;
	}
}

static void
radeon_atom_encoder_dpms_ext(struct drm_encoder *encoder,
			     struct drm_encoder *ext_encoder,
			     int mode)
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;

	switch (mode) {
	case DRM_MODE_DPMS_ON:
	default:
		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) {
			atombios_external_encoder_setup(encoder, ext_encoder,
							EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
			atombios_external_encoder_setup(encoder, ext_encoder,
							EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
		} else
			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
		break;
	case DRM_MODE_DPMS_STANDBY:
	case DRM_MODE_DPMS_SUSPEND:
	case DRM_MODE_DPMS_OFF:
		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) {
			atombios_external_encoder_setup(encoder, ext_encoder,
							EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
			atombios_external_encoder_setup(encoder, ext_encoder,
							EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
		} else
			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
		break;
		break;
	}
	}
}
}
@@ -1747,7 +1737,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
	struct drm_device *dev = encoder->dev;
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
	struct radeon_device *rdev = dev->dev_private;
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);


	DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
	DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
		  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
		  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
@@ -1807,9 +1796,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
		return;
		return;
	}
	}


	if (ext_encoder)
		radeon_atom_encoder_dpms_ext(encoder, ext_encoder, mode);

	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);


}
}