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

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

drm/radeon/kms: enable hpd support



This enabled interrupt driven hpd support for all
radeon chips.  Assuming the hpd pin is wired up
correctly, the driver will generate uevents on
digital monitor connect and disconnect and retrain
DP monitors automatically.

Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 429770b3
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -507,6 +507,18 @@ static bool atom_dp_get_link_status(struct radeon_connector *radeon_connector,
	return true;
}

bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector)
{
	struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
	u8 link_status[DP_LINK_STATUS_SIZE];

	if (!atom_dp_get_link_status(radeon_connector, link_status))
		return false;
	if (dp_channel_eq_ok(link_status, dig_connector->dp_lane_count))
		return false;
	return true;
}

static void dp_set_power(struct radeon_connector *radeon_connector, u8 power_state)
{
	struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
+7 −2
Original line number Diff line number Diff line
@@ -289,6 +289,7 @@ static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
int r100_irq_process(struct radeon_device *rdev)
{
	uint32_t status, msi_rearm;
	bool queue_hotplug = false;

	status = r100_irq_ack(rdev);
	if (!status) {
@@ -310,13 +311,17 @@ int r100_irq_process(struct radeon_device *rdev)
			drm_handle_vblank(rdev->ddev, 1);
		}
		if (status & RADEON_FP_DETECT_STAT) {
			DRM_INFO("HPD1\n");
			queue_hotplug = true;
			DRM_DEBUG("HPD1\n");
		}
		if (status & RADEON_FP2_DETECT_STAT) {
			DRM_INFO("HPD2\n");
			queue_hotplug = true;
			DRM_DEBUG("HPD2\n");
		}
		status = r100_irq_ack(rdev);
	}
	if (queue_hotplug)
		queue_work(rdev->wq, &rdev->hotplug_work);
	if (rdev->msi_enabled) {
		switch (rdev->family) {
		case CHIP_RS400:
+15 −6
Original line number Diff line number Diff line
@@ -2674,6 +2674,7 @@ int r600_irq_process(struct radeon_device *rdev)
	u32 last_entry = rdev->ih.ring_size - 16;
	u32 ring_index, disp_int, disp_int_cont, disp_int_cont2;
	unsigned long flags;
	bool queue_hotplug = false;

	DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);

@@ -2745,37 +2746,43 @@ restart_ih:
			case 0:
				if (disp_int & DC_HPD1_INTERRUPT) {
					disp_int &= ~DC_HPD1_INTERRUPT;
					DRM_INFO("IH: HPD1\n");
					queue_hotplug = true;
					DRM_DEBUG("IH: HPD1\n");
				}
				break;
			case 1:
				if (disp_int & DC_HPD2_INTERRUPT) {
					disp_int &= ~DC_HPD2_INTERRUPT;
					DRM_INFO("IH: HPD2\n");
					queue_hotplug = true;
					DRM_DEBUG("IH: HPD2\n");
				}
				break;
			case 4:
				if (disp_int_cont & DC_HPD3_INTERRUPT) {
					disp_int_cont &= ~DC_HPD3_INTERRUPT;
					DRM_INFO("IH: HPD3\n");
					queue_hotplug = true;
					DRM_DEBUG("IH: HPD3\n");
				}
				break;
			case 5:
				if (disp_int_cont & DC_HPD4_INTERRUPT) {
					disp_int_cont &= ~DC_HPD4_INTERRUPT;
					DRM_INFO("IH: HPD4\n");
					queue_hotplug = true;
					DRM_DEBUG("IH: HPD4\n");
				}
				break;
			case 10:
				if (disp_int_cont2 & DC_HPD5_INTERRUPT) {
					disp_int_cont &= ~DC_HPD5_INTERRUPT;
					DRM_INFO("IH: HPD5\n");
					queue_hotplug = true;
					DRM_DEBUG("IH: HPD5\n");
				}
				break;
			case 12:
				if (disp_int_cont2 & DC_HPD6_INTERRUPT) {
					disp_int_cont &= ~DC_HPD6_INTERRUPT;
					DRM_INFO("IH: HPD6\n");
					queue_hotplug = true;
					DRM_DEBUG("IH: HPD6\n");
				}
				break;
			default:
@@ -2807,6 +2814,8 @@ restart_ih:
	wptr = r600_get_ih_wptr(rdev);
	if (wptr != rdev->ih.wptr)
		goto restart_ih;
	if (queue_hotplug)
		queue_work(rdev->wq, &rdev->hotplug_work);
	rdev->ih.rptr = rptr;
	WREG32(IH_RB_RPTR, rdev->ih.rptr);
	spin_unlock_irqrestore(&rdev->ih.lock, flags);
+2 −0
Original line number Diff line number Diff line
@@ -809,6 +809,8 @@ struct radeon_device {
	struct r600_blit r600_blit;
	int msi_enabled; /* msi enabled */
	struct r600_ih ih; /* r6/700 interrupt ring */
	struct workqueue_struct *wq;
	struct work_struct hotplug_work;
};

int radeon_device_init(struct radeon_device *rdev,
+20 −0
Original line number Diff line number Diff line
@@ -40,6 +40,26 @@ radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
				       struct drm_encoder *encoder,
				       bool connected);

void radeon_connector_hotplug(struct drm_connector *connector)
{
	struct drm_device *dev = connector->dev;
	struct radeon_device *rdev = dev->dev_private;
	struct radeon_connector *radeon_connector = to_radeon_connector(connector);

	if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);

	if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
		if (radeon_dp_getsinktype(radeon_connector) == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
			if (radeon_dp_needs_link_train(radeon_connector)) {
				if (connector->encoder)
					dp_link_train(connector->encoder, connector);
			}
		}
	}

}

static void radeon_property_change_mode(struct drm_encoder *encoder)
{
	struct drm_crtc *crtc = encoder->crtc;
Loading