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

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

drm/radeon/kms/atom: rework encoder dpms



The existing function was getting too big and complex.
Break it down into a more manageable set of functions.

Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent fdca78c3
Loading
Loading
Loading
Loading
+186 −152
Original line number Original line Diff line number Diff line
@@ -1356,44 +1356,24 @@ atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
}
}


static void
static void
radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
radeon_atom_encoder_dpms_avivo(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_atom_get_external_encoder(encoder);
	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
	int index = 0;
	int index = 0;
	bool is_dig = false;
	bool is_dce5_dac = false;
	bool is_dce5_dvo = false;


	memset(&args, 0, sizeof(args));
	memset(&args, 0, sizeof(args));


	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->active_device);
	switch (radeon_encoder->encoder_id) {
	switch (radeon_encoder->encoder_id) {
	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
		break;
		break;
	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
		is_dig = true;
		break;
	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
	case ENCODER_OBJECT_ID_INTERNAL_DDI:
	case ENCODER_OBJECT_ID_INTERNAL_DDI:
		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
		break;
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
		if (ASIC_IS_DCE5(rdev))
			is_dce5_dvo = true;
		else if (ASIC_IS_DCE3(rdev))
			is_dig = true;
		else
		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
		break;
		break;
	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
@@ -1407,16 +1387,12 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
		break;
		break;
	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
		if (ASIC_IS_DCE5(rdev))
			is_dce5_dac = true;
		else {
		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
		else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
		else
		else
			index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
			index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
		}
		break;
		break;
	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
@@ -1427,9 +1403,54 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
		else
		else
			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
		break;
		break;
	default:
		return;
	}

	switch (mode) {
	case DRM_MODE_DPMS_ON:
		args.ucAction = ATOM_ENABLE;
		/* workaround for DVOOutputControl on some RS690 systems */
		if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
			u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
			WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
			WREG32(RADEON_BIOS_3_SCRATCH, reg);
		} else
			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
			args.ucAction = ATOM_LCD_BLON;
			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
		}
		break;
	case DRM_MODE_DPMS_STANDBY:
	case DRM_MODE_DPMS_SUSPEND:
	case DRM_MODE_DPMS_OFF:
		args.ucAction = ATOM_DISABLE;
		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
			args.ucAction = ATOM_LCD_BLOFF;
			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
		}
		break;
	}
}

static void
radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
{
	struct drm_device *dev = encoder->dev;
	struct radeon_device *rdev = dev->dev_private;
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
	struct radeon_connector *radeon_connector = NULL;
	struct radeon_connector_atom_dig *radeon_dig_connector = NULL;

	if (connector) {
		radeon_connector = to_radeon_connector(connector);
		radeon_dig_connector = radeon_connector->con_priv;
	}
	}


	if (is_dig) {
	switch (mode) {
	switch (mode) {
	case DRM_MODE_DPMS_ON:
	case DRM_MODE_DPMS_ON:
		/* some early dce3.2 boards have a bug in their transmitter control table */
		/* some early dce3.2 boards have a bug in their transmitter control table */
@@ -1437,14 +1458,8 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
		else
		else
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
			if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
		if ((atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) && connector) {
				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {

				if (connector &&
				    (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
					struct radeon_connector *radeon_connector = to_radeon_connector(connector);
					struct radeon_connector_atom_dig *radeon_dig_connector =
						radeon_connector->con_priv;
				atombios_set_edp_panel_power(connector,
				atombios_set_edp_panel_power(connector,
							     ATOM_TRANSMITTER_ACTION_POWER_ON);
							     ATOM_TRANSMITTER_ACTION_POWER_ON);
				radeon_dig_connector->edp_on = true;
				radeon_dig_connector->edp_on = true;
@@ -1462,16 +1477,10 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
	case DRM_MODE_DPMS_SUSPEND:
	case DRM_MODE_DPMS_SUSPEND:
	case DRM_MODE_DPMS_OFF:
	case DRM_MODE_DPMS_OFF:
		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
			if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
		if ((atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) && connector) {
				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);

			if (ASIC_IS_DCE4(rdev))
			if (ASIC_IS_DCE4(rdev))
				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
				if (connector &&
			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
				    (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
					struct radeon_connector *radeon_connector = to_radeon_connector(connector);
					struct radeon_connector_atom_dig *radeon_dig_connector =
						radeon_connector->con_priv;
				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;
@@ -1481,18 +1490,71 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
		break;
		break;
	}
	}
	} else if (is_dce5_dac) {
}

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) {
	switch (mode) {
	case DRM_MODE_DPMS_ON:
	case DRM_MODE_DPMS_ON:
			atombios_dac_setup(encoder, ATOM_ENABLE);
	default:
		if (ASIC_IS_DCE41(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;
		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:
			atombios_dac_setup(encoder, ATOM_DISABLE);
		if (ASIC_IS_DCE41(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;
	}
	}
	} else if (is_dce5_dvo) {
}

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

	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->active_device);
	switch (radeon_encoder->encoder_id) {
	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
	case ENCODER_OBJECT_ID_INTERNAL_DDI:
	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
		radeon_atom_encoder_dpms_avivo(encoder, mode);
		break;
	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
		radeon_atom_encoder_dpms_dig(encoder, mode);
		break;
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
		if (ASIC_IS_DCE5(rdev)) {
			switch (mode) {
			switch (mode) {
			case DRM_MODE_DPMS_ON:
			case DRM_MODE_DPMS_ON:
				atombios_dvo_setup(encoder, ATOM_ENABLE);
				atombios_dvo_setup(encoder, ATOM_ENABLE);
@@ -1503,62 +1565,34 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
				atombios_dvo_setup(encoder, ATOM_DISABLE);
				atombios_dvo_setup(encoder, ATOM_DISABLE);
				break;
				break;
			}
			}
	} else {
		} else if (ASIC_IS_DCE3(rdev))
			radeon_atom_encoder_dpms_dig(encoder, mode);
		else
			radeon_atom_encoder_dpms_avivo(encoder, mode);
		break;
	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
		if (ASIC_IS_DCE5(rdev)) {
			switch (mode) {
			switch (mode) {
			case DRM_MODE_DPMS_ON:
			case DRM_MODE_DPMS_ON:
			args.ucAction = ATOM_ENABLE;
				atombios_dac_setup(encoder, ATOM_ENABLE);
			/* workaround for DVOOutputControl on some RS690 systems */
			if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
				u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
				WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
				WREG32(RADEON_BIOS_3_SCRATCH, reg);
			} else
				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
				args.ucAction = ATOM_LCD_BLON;
				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
			}
				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:
			args.ucAction = ATOM_DISABLE;
				atombios_dac_setup(encoder, ATOM_DISABLE);
			atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
				args.ucAction = ATOM_LCD_BLOFF;
				atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
			}
				break;
				break;
			}
			}
	}

	if (ext_encoder) {
		switch (mode) {
		case DRM_MODE_DPMS_ON:
		default:
			if (ASIC_IS_DCE41(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
		} else
				atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
			radeon_atom_encoder_dpms_avivo(encoder, mode);
		break;
		break;
		case DRM_MODE_DPMS_STANDBY:
	default:
		case DRM_MODE_DPMS_SUSPEND:
		return;
		case DRM_MODE_DPMS_OFF:
			if (ASIC_IS_DCE41(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;
		}
	}
	}


	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);


}
}