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

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

drm/radeon/kms: handle DP bridges



Fusion hardware often has DP to VGA/LVDS/TMDS bridges to
handle non-DP encoders.  Internally we treat them mostly
like DP.

Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 834b2904
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -557,7 +557,8 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
			if (connector)
				bpc = connector->display_info.bpc;
			encoder_mode = atombios_get_encoder_mode(encoder);
			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) {
			if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
			    radeon_encoder_is_dp_bridge(encoder)) {
				if (connector) {
					struct radeon_connector *radeon_connector = to_radeon_connector(connector);
					struct radeon_connector_atom_dig *dig_connector =
@@ -637,7 +638,8 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
				if (ss_enabled && ss->percentage)
					args.v3.sInput.ucDispPllConfig |=
						DISPPLL_CONFIG_SS_ENABLE;
				if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
				if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT) ||
				    radeon_encoder_is_dp_bridge(encoder)) {
					struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
					if (encoder_mode == ATOM_ENCODER_MODE_DP) {
						args.v3.sInput.ucDispPllConfig |=
+256 −177
Original line number Diff line number Diff line
@@ -1230,8 +1230,11 @@ radeon_add_atom_connector(struct drm_device *dev,
	struct drm_connector *connector;
	struct radeon_connector *radeon_connector;
	struct radeon_connector_atom_dig *radeon_dig_connector;
	struct drm_encoder *encoder;
	struct radeon_encoder *radeon_encoder;
	uint32_t subpixel_order = SubPixelNone;
	bool shared_ddc = false;
	bool is_dp_bridge = false;

	if (connector_type == DRM_MODE_CONNECTOR_Unknown)
		return;
@@ -1263,6 +1266,21 @@ radeon_add_atom_connector(struct drm_device *dev,
		}
	}

	/* check if it's a dp bridge */
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
		radeon_encoder = to_radeon_encoder(encoder);
		if (radeon_encoder->devices & supported_device) {
			switch (radeon_encoder->encoder_id) {
			case ENCODER_OBJECT_ID_TRAVIS:
			case ENCODER_OBJECT_ID_NUTMEG:
				is_dp_bridge = true;
				break;
			default:
				break;
			}
		}
	}

	radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL);
	if (!radeon_connector)
		return;
@@ -1280,6 +1298,66 @@ radeon_add_atom_connector(struct drm_device *dev,
		if (!radeon_connector->router_bus)
			DRM_ERROR("Failed to assign router i2c bus! Check dmesg for i2c errors.\n");
	}

	if (is_dp_bridge) {
		radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
		if (!radeon_dig_connector)
			goto failed;
		radeon_dig_connector->igp_lane_info = igp_lane_info;
		radeon_connector->con_priv = radeon_dig_connector;
		drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type);
		drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
		if (i2c_bus->valid) {
			/* add DP i2c bus */
			if (connector_type == DRM_MODE_CONNECTOR_eDP)
				radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch");
			else
				radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch");
			if (!radeon_dig_connector->dp_i2c_bus)
				DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n");
			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
			if (!radeon_connector->ddc_bus)
				DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
		}
		switch (connector_type) {
		case DRM_MODE_CONNECTOR_VGA:
		case DRM_MODE_CONNECTOR_DVIA:
		default:
			connector->interlace_allowed = true;
			connector->doublescan_allowed = true;
			break;
		case DRM_MODE_CONNECTOR_DVII:
		case DRM_MODE_CONNECTOR_DVID:
		case DRM_MODE_CONNECTOR_HDMIA:
		case DRM_MODE_CONNECTOR_HDMIB:
		case DRM_MODE_CONNECTOR_DisplayPort:
			drm_connector_attach_property(&radeon_connector->base,
						      rdev->mode_info.underscan_property,
						      UNDERSCAN_OFF);
			drm_connector_attach_property(&radeon_connector->base,
						      rdev->mode_info.underscan_hborder_property,
						      0);
			drm_connector_attach_property(&radeon_connector->base,
						      rdev->mode_info.underscan_vborder_property,
						      0);
			subpixel_order = SubPixelHorizontalRGB;
			connector->interlace_allowed = true;
			if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
				connector->doublescan_allowed = true;
			else
				connector->doublescan_allowed = false;
			break;
		case DRM_MODE_CONNECTOR_LVDS:
		case DRM_MODE_CONNECTOR_eDP:
			drm_connector_attach_property(&radeon_connector->base,
						      dev->mode_config.scaling_mode_property,
						      DRM_MODE_SCALE_FULLSCREEN);
			subpixel_order = SubPixelHorizontalRGB;
			connector->interlace_allowed = false;
			connector->doublescan_allowed = false;
			break;
		}
	} else {
		switch (connector_type) {
		case DRM_MODE_CONNECTOR_VGA:
			drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
@@ -1490,6 +1568,7 @@ radeon_add_atom_connector(struct drm_device *dev,
			connector->doublescan_allowed = false;
			break;
		}
	}

	if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
		if (i2c_bus->valid)
+3 −2
Original line number Diff line number Diff line
@@ -1949,8 +1949,9 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);

	if (radeon_encoder->active_device &
	    (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) {
	if ((radeon_encoder->active_device &
	     (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
	    radeon_encoder_is_dp_bridge(encoder)) {
		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
		if (dig)
			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);