Hi,

attached is the next version of the IRQ support patch for HDMI audio on
radeon hardware. The following changes (mostly suggested by Alex) were
made:
1. Using the common asic irq functions now.
2. Using rdev->irq.installed instead of rdev->ih.enabled.
3. Disabling irq support for RS600/690/740 were it isn't expected to be
working.
4. Start using defines for the individual bits instead of spreading
magic numbers all around.

A drawback is that I still couldn't find the time to test it my RV710.

Christian.
>From cc9ec18c9e31b1bd0ca19b5729ffed1e3b4a6e2d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20K=C3=B6nig?= <deathsim...@vodafone.de>
Date: Mon, 5 Apr 2010 22:14:55 +0200
Subject: [PATCH 1/2] drm/radeon/kms: rework audio polling timer
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Rework HDMI audio polling timer, only enable it when
at least one HDMI encoder needs it. Preparation for
replacing it with irq support.

Signed-off-by: Christian König <deathsim...@vodafone.de>
---
 drivers/gpu/drm/radeon/r600_audio.c  |   55 +++++++++++++++++++++++++--------
 drivers/gpu/drm/radeon/r600_hdmi.c   |   17 +++++++----
 drivers/gpu/drm/radeon/radeon.h      |   14 +++++----
 drivers/gpu/drm/radeon/radeon_mode.h |    1 +
 4 files changed, 61 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c
index dac7042..03bf8bc 100644
--- a/drivers/gpu/drm/radeon/r600_audio.c
+++ b/drivers/gpu/drm/radeon/r600_audio.c
@@ -44,7 +44,7 @@ static int r600_audio_chipset_supported(struct radeon_device *rdev)
 /*
  * current number of channels
  */
-static int r600_audio_channels(struct radeon_device *rdev)
+int r600_audio_channels(struct radeon_device *rdev)
 {
 	return (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0x7) + 1;
 }
@@ -52,7 +52,7 @@ static int r600_audio_channels(struct radeon_device *rdev)
 /*
  * current bits per sample
  */
-static int r600_audio_bits_per_sample(struct radeon_device *rdev)
+int r600_audio_bits_per_sample(struct radeon_device *rdev)
 {
 	uint32_t value = (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0xF0) >> 4;
 	switch (value) {
@@ -71,7 +71,7 @@ static int r600_audio_bits_per_sample(struct radeon_device *rdev)
 /*
  * current sampling rate in HZ
  */
-static int r600_audio_rate(struct radeon_device *rdev)
+int r600_audio_rate(struct radeon_device *rdev)
 {
 	uint32_t value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL);
 	uint32_t result;
@@ -90,7 +90,7 @@ static int r600_audio_rate(struct radeon_device *rdev)
 /*
  * iec 60958 status bits
  */
-static uint8_t r600_audio_status_bits(struct radeon_device *rdev)
+uint8_t r600_audio_status_bits(struct radeon_device *rdev)
 {
 	return RREG32(R600_AUDIO_STATUS_BITS) & 0xff;
 }
@@ -98,7 +98,7 @@ static uint8_t r600_audio_status_bits(struct radeon_device *rdev)
 /*
  * iec 60958 category code
  */
-static uint8_t r600_audio_category_code(struct radeon_device *rdev)
+uint8_t r600_audio_category_code(struct radeon_device *rdev)
 {
 	return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff;
 }
@@ -118,7 +118,7 @@ static void r600_audio_update_hdmi(unsigned long param)
 	uint8_t category_code = r600_audio_category_code(rdev);
 
 	struct drm_encoder *encoder;
-	int changes = 0;
+	int changes = 0, still_going = 0;
 
 	changes |= channels != rdev->audio_channels;
 	changes |= rate != rdev->audio_rate;
@@ -135,15 +135,17 @@ static void r600_audio_update_hdmi(unsigned long param)
 	}
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		if (changes || r600_hdmi_buffer_status_changed(encoder))
-			r600_hdmi_update_audio_settings(
-				encoder, channels,
-				rate, bps, status_bits,
-				category_code);
+		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+		if (radeon_encoder->audio_polling_active) {
+			still_going = 1;
+			if (changes || r600_hdmi_buffer_status_changed(encoder))
+				r600_hdmi_update_audio_settings(encoder);
+		}
 	}
 
-	mod_timer(&rdev->audio_timer,
-		jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL));
+	if(still_going)
+		mod_timer(&rdev->audio_timer,
+			jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL));
 }
 
 /*
@@ -176,9 +178,34 @@ int r600_audio_init(struct radeon_device *rdev)
 		r600_audio_update_hdmi,
 		(unsigned long)rdev);
 
+	return 0;
+}
+
+/*
+ * enable the polling timer, to check for status changes
+ */
+void r600_audio_enable_polling(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+	DRM_DEBUG("r600_audio_enable_polling: %d", radeon_encoder->audio_polling_active);
+	if (radeon_encoder->audio_polling_active)
+		return;
+
+	radeon_encoder->audio_polling_active = 1;
 	mod_timer(&rdev->audio_timer, jiffies + 1);
+}
 
-	return 0;
+/*
+ * disable the polling timer, so we get no more status updates
+ */
+void r600_audio_disable_polling(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	DRM_DEBUG("r600_audio_disable_polling: %d", radeon_encoder->audio_polling_active);
+	radeon_encoder->audio_polling_active = 0;
 }
 
 /*
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index 029fa14..1960ac3 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -350,17 +350,18 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
 /*
  * update settings with current parameters from audio engine
  */
-void r600_hdmi_update_audio_settings(struct drm_encoder *encoder,
-				     int channels,
-				     int rate,
-				     int bps,
-				     uint8_t status_bits,
-				     uint8_t category_code)
+void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
 
+	int channels = r600_audio_channels(rdev);
+	int rate = r600_audio_rate(rdev);
+	int bps = r600_audio_bits_per_sample(rdev);
+	uint8_t status_bits = r600_audio_status_bits(rdev);
+	uint8_t category_code = r600_audio_category_code(rdev);
+
 	uint32_t iec;
 
 	if (!offset)
@@ -512,6 +513,8 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
 		}
 	}
 
+	r600_audio_enable_polling(encoder);
+
 	DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n",
 		radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
 }
@@ -530,6 +533,8 @@ void r600_hdmi_disable(struct drm_encoder *encoder)
 		return;
 	}
 
+	r600_audio_disable_polling(encoder);
+
 	DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n",
 		radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
 
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 034218c..5baf7fd 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1287,18 +1287,20 @@ extern void r600_irq_suspend(struct radeon_device *rdev);
 extern int r600_audio_init(struct radeon_device *rdev);
 extern int r600_audio_tmds_index(struct drm_encoder *encoder);
 extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock);
+extern int r600_audio_channels(struct radeon_device *rdev);
+extern int r600_audio_bits_per_sample(struct radeon_device *rdev);
+extern int r600_audio_rate(struct radeon_device *rdev);
+extern uint8_t r600_audio_status_bits(struct radeon_device *rdev);
+extern uint8_t r600_audio_category_code(struct radeon_device *rdev);
+extern void r600_audio_enable_polling(struct drm_encoder *encoder);
+extern void r600_audio_disable_polling(struct drm_encoder *encoder);
 extern void r600_audio_fini(struct radeon_device *rdev);
 extern void r600_hdmi_init(struct drm_encoder *encoder);
 extern void r600_hdmi_enable(struct drm_encoder *encoder);
 extern void r600_hdmi_disable(struct drm_encoder *encoder);
 extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
 extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
-extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder,
-					    int channels,
-					    int rate,
-					    int bps,
-					    uint8_t status_bits,
-					    uint8_t category_code);
+extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
 
 /* evergreen */
 struct evergreen_mc_save {
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 0b8e327..715bfb7 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -339,6 +339,7 @@ struct radeon_encoder {
 	enum radeon_rmx_type rmx_type;
 	struct drm_display_mode native_mode;
 	void *enc_priv;
+	int audio_polling_active;
 	int hdmi_offset;
 	int hdmi_config_offset;
 	int hdmi_audio_workaround;
-- 
1.7.0

>From 1658a5093ee03b951738ac376a3fafb5707d279b Mon Sep 17 00:00:00 2001
From: Christian Koenig <deathsim...@vodafone.de>
Date: Sat, 10 Apr 2010 03:13:16 +0200
Subject: [PATCH 2/2] drm/radeon/kms: HDMI irq support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Implements irq support for HDMI audio output. Now the polling timer
is only enabled if irq support isn't available.

Signed-off-by: Christian König <deathsim...@vodafone.de>
---
 drivers/gpu/drm/radeon/r600.c       |   33 ++++++++++++++++++++
 drivers/gpu/drm/radeon/r600_audio.c |   21 ++++++++-----
 drivers/gpu/drm/radeon/r600_hdmi.c  |   53 +++++++++++++++++++-------------
 drivers/gpu/drm/radeon/r600_reg.h   |   57 ++++++++++++++++++----------------
 drivers/gpu/drm/radeon/radeon.h     |    3 ++
 5 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 8f3454e..421b485 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2500,6 +2500,7 @@ int r600_irq_set(struct radeon_device *rdev)
 	u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE;
 	u32 mode_int = 0;
 	u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0;
+	u32 hdmi1, hdmi2;
 
 	if (!rdev->irq.installed) {
 		WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n");
@@ -2513,7 +2514,9 @@ int r600_irq_set(struct radeon_device *rdev)
 		return 0;
 	}
 
+	hdmi1 = RREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN;
 	if (ASIC_IS_DCE3(rdev)) {
+		hdmi2 = RREG32(R600_HDMI_BLOCK3 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN;
 		hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
 		hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
 		hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
@@ -2523,6 +2526,7 @@ int r600_irq_set(struct radeon_device *rdev)
 			hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
 		}
 	} else {
+		hdmi2 = RREG32(R600_HDMI_BLOCK2 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN;
 		hpd1 = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & ~DC_HPDx_INT_EN;
 		hpd2 = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~DC_HPDx_INT_EN;
 		hpd3 = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN;
@@ -2564,10 +2568,20 @@ int r600_irq_set(struct radeon_device *rdev)
 		DRM_DEBUG("r600_irq_set: hpd 6\n");
 		hpd6 |= DC_HPDx_INT_EN;
 	}
+	if (rdev->irq.hdmi[0]) {
+		DRM_DEBUG("r600_irq_set: hdmi 1\n");
+		hdmi1 |= R600_HDMI_INT_EN;
+	}
+	if (rdev->irq.hdmi[1]) {
+		DRM_DEBUG("r600_irq_set: hdmi 2\n");
+		hdmi2 |= R600_HDMI_INT_EN;
+	}
 
 	WREG32(CP_INT_CNTL, cp_int_cntl);
 	WREG32(DxMODE_INT_MASK, mode_int);
+	WREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, hdmi1);
 	if (ASIC_IS_DCE3(rdev)) {
+		WREG32(R600_HDMI_BLOCK3 + R600_HDMI_CNTL, hdmi2);
 		WREG32(DC_HPD1_INT_CONTROL, hpd1);
 		WREG32(DC_HPD2_INT_CONTROL, hpd2);
 		WREG32(DC_HPD3_INT_CONTROL, hpd3);
@@ -2577,6 +2591,7 @@ int r600_irq_set(struct radeon_device *rdev)
 			WREG32(DC_HPD6_INT_CONTROL, hpd6);
 		}
 	} else {
+		WREG32(R600_HDMI_BLOCK2 + R600_HDMI_CNTL, hdmi2);
 		WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1);
 		WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2);
 		WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, hpd3);
@@ -2660,6 +2675,18 @@ static inline void r600_irq_ack(struct radeon_device *rdev,
 			WREG32(DC_HPD6_INT_CONTROL, tmp);
 		}
 	}
+	if (RREG32(R600_HDMI_BLOCK1 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) {
+		WREG32_P(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK);
+	}
+	if (ASIC_IS_DCE3(rdev)) {
+		if (RREG32(R600_HDMI_BLOCK3 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) {
+			WREG32_P(R600_HDMI_BLOCK3 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK);
+		}
+	} else {
+		if (RREG32(R600_HDMI_BLOCK2 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) {
+			WREG32_P(R600_HDMI_BLOCK2 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK);
+		}
+	}
 }
 
 void r600_irq_disable(struct radeon_device *rdev)
@@ -2713,6 +2740,8 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev)
  *     19         1  FP Hot plug detection B
  *     19         2  DAC A auto-detection
  *     19         3  DAC B auto-detection
+ *     21         4  HDMI block A
+ *     21         5  HDMI block B
  *    176         -  CP_INT RB
  *    177         -  CP_INT IB1
  *    178         -  CP_INT IB2
@@ -2852,6 +2881,10 @@ restart_ih:
 				break;
 			}
 			break;
+		case 21: /* HDMI */
+			DRM_DEBUG("IH: HDMI: 0x%x\n", src_data);
+			r600_audio_schedule_polling(rdev);
+			break;
 		case 176: /* CP_INT in ring buffer */
 		case 177: /* CP_INT in IB1 */
 		case 178: /* CP_INT in IB2 */
diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c
index 03bf8bc..89d8dc9 100644
--- a/drivers/gpu/drm/radeon/r600_audio.c
+++ b/drivers/gpu/drm/radeon/r600_audio.c
@@ -104,6 +104,15 @@ uint8_t r600_audio_category_code(struct radeon_device *rdev)
 }
 
 /*
+ * schedule next audio update event
+ */
+void r600_audio_schedule_polling(struct radeon_device *rdev)
+{
+	mod_timer(&rdev->audio_timer,
+		jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL));
+}
+
+/*
  * update all hdmi interfaces with current audio parameters
  */
 static void r600_audio_update_hdmi(unsigned long param)
@@ -136,16 +145,12 @@ static void r600_audio_update_hdmi(unsigned long param)
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-		if (radeon_encoder->audio_polling_active) {
-			still_going = 1;
-			if (changes || r600_hdmi_buffer_status_changed(encoder))
-				r600_hdmi_update_audio_settings(encoder);
-		}
+		still_going |= radeon_encoder->audio_polling_active;
+		if (changes || r600_hdmi_buffer_status_changed(encoder))
+			r600_hdmi_update_audio_settings(encoder);
 	}
 
-	if(still_going)
-		mod_timer(&rdev->audio_timer,
-			jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL));
+	if(still_going) r600_audio_schedule_polling(rdev);
 }
 
 /*
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index 1960ac3..753c9a9 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -290,17 +290,15 @@ void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
 	if (!offset)
 		return;
 
-	if (r600_hdmi_is_audio_buffer_filled(encoder)) {
-		/* disable audio workaround and start delivering of audio frames */
-		WREG32_P(offset+R600_HDMI_CNTL, 0x00000001, ~0x00001001);
+	if (!radeon_encoder->hdmi_audio_workaround ||
+		r600_hdmi_is_audio_buffer_filled(encoder)) {
 
-	} else if (radeon_encoder->hdmi_audio_workaround) {
-		/* enable audio workaround and start delivering of audio frames */
-		WREG32_P(offset+R600_HDMI_CNTL, 0x00001001, ~0x00001001);
+		/* disable audio workaround */
+		WREG32_P(offset+R600_HDMI_CNTL, 0x00000001, ~0x00001001);
 
 	} else {
-		/* disable audio workaround and stop delivering of audio frames */
-		WREG32_P(offset+R600_HDMI_CNTL, 0x00000000, ~0x00001001);
+		/* enable audio workaround */
+		WREG32_P(offset+R600_HDMI_CNTL, 0x00001001, ~0x00001001);
 	}
 }
 
@@ -342,9 +340,6 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
 
 	/* audio packets per line, does anyone know how to calc this ? */
 	WREG32_P(offset+R600_HDMI_CNTL, 0x00040000, ~0x001F0000);
-
-	/* update? reset? don't realy know */
-	WREG32_P(offset+R600_HDMI_CNTL, 0x14000000, ~0x14000000);
 }
 
 /*
@@ -413,9 +408,6 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
 	r600_hdmi_audioinfoframe(encoder, channels-1, 0, 0, 0, 0, 0, 0, 0);
 
 	r600_hdmi_audio_workaround(encoder);
-
-	/* update? reset? don't realy know */
-	WREG32_P(offset+R600_HDMI_CNTL, 0x04000000, ~0x04000000);
 }
 
 static int r600_hdmi_find_free_block(struct drm_device *dev)
@@ -484,6 +476,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t offset;
 
 	if (!radeon_encoder->hdmi_offset) {
 		r600_hdmi_assign_block(encoder);
@@ -494,10 +487,10 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
 		}
 	}
 
+	offset = radeon_encoder->hdmi_offset;
 	if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) {
 		WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0x1, ~0x1);
 	} else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
-		int offset = radeon_encoder->hdmi_offset;
 		switch (radeon_encoder->encoder_id) {
 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
 			WREG32_P(AVIVO_TMDSA_CNTL, 0x4, ~0x4);
@@ -513,7 +506,20 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
 		}
 	}
 
-	r600_audio_enable_polling(encoder);
+	if (rdev->irq.installed
+	    && rdev->family != CHIP_RS600
+	    && rdev->family != CHIP_RS690
+	    && rdev->family != CHIP_RS740) {
+
+		/* if irq is available use it */
+		rdev->irq.hdmi[offset == R600_HDMI_BLOCK1 ? 0 : 1] = true;
+		radeon_irq_set(rdev);
+
+		r600_audio_disable_polling(encoder);
+	} else {
+		/* if not fallback to polling */
+		r600_audio_enable_polling(encoder);
+	}
 
 	DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n",
 		radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
@@ -527,21 +533,26 @@ void r600_hdmi_disable(struct drm_encoder *encoder)
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint8_t offset = radeon_encoder->hdmi_offset;
 
-	if (!radeon_encoder->hdmi_offset) {
+	if (!offset) {
 		dev_err(rdev->dev, "Disabling not enabled HDMI\n");
 		return;
 	}
 
-	r600_audio_disable_polling(encoder);
-
 	DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n",
-		radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
+		offset, radeon_encoder->encoder_id);
+
+	/* disable irq */
+	rdev->irq.hdmi[offset == R600_HDMI_BLOCK1 ? 0 : 1] = false;
+	radeon_irq_set(rdev);
+
+	/* disable polling */
+	r600_audio_disable_polling(encoder);
 
 	if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) {
 		WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0, ~0x1);
 	} else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
-		int offset = radeon_encoder->hdmi_offset;
 		switch (radeon_encoder->encoder_id) {
 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
 			WREG32_P(AVIVO_TMDSA_CNTL, 0, ~0x4);
diff --git a/drivers/gpu/drm/radeon/r600_reg.h b/drivers/gpu/drm/radeon/r600_reg.h
index 7b1d223..d84612a 100644
--- a/drivers/gpu/drm/radeon/r600_reg.h
+++ b/drivers/gpu/drm/radeon/r600_reg.h
@@ -157,33 +157,36 @@
 #define R600_HDMI_BLOCK3                  0x7800
 
 /* HDMI registers */
-#define R600_HDMI_ENABLE           0x00
-#define R600_HDMI_STATUS           0x04
-#define R600_HDMI_CNTL             0x08
-#define R600_HDMI_UNKNOWN_0        0x0C
-#define R600_HDMI_AUDIOCNTL        0x10
-#define R600_HDMI_VIDEOCNTL        0x14
-#define R600_HDMI_VERSION          0x18
-#define R600_HDMI_UNKNOWN_1        0x28
-#define R600_HDMI_VIDEOINFOFRAME_0 0x54
-#define R600_HDMI_VIDEOINFOFRAME_1 0x58
-#define R600_HDMI_VIDEOINFOFRAME_2 0x5c
-#define R600_HDMI_VIDEOINFOFRAME_3 0x60
-#define R600_HDMI_32kHz_CTS        0xac
-#define R600_HDMI_32kHz_N          0xb0
-#define R600_HDMI_44_1kHz_CTS      0xb4
-#define R600_HDMI_44_1kHz_N        0xb8
-#define R600_HDMI_48kHz_CTS        0xbc
-#define R600_HDMI_48kHz_N          0xc0
-#define R600_HDMI_AUDIOINFOFRAME_0 0xcc
-#define R600_HDMI_AUDIOINFOFRAME_1 0xd0
-#define R600_HDMI_IEC60958_1       0xd4
-#define R600_HDMI_IEC60958_2       0xd8
-#define R600_HDMI_UNKNOWN_2        0xdc
-#define R600_HDMI_AUDIO_DEBUG_0    0xe0
-#define R600_HDMI_AUDIO_DEBUG_1    0xe4
-#define R600_HDMI_AUDIO_DEBUG_2    0xe8
-#define R600_HDMI_AUDIO_DEBUG_3    0xec
+#define R600_HDMI_ENABLE                0x00
+#define R600_HDMI_STATUS                0x04
+#       define R600_HDMI_INT_PENDING    (1 << 29)
+#define R600_HDMI_CNTL                  0x08
+#       define R600_HDMI_INT_EN         (1 << 28)
+#       define R600_HDMI_INT_ACK        (1 << 29)
+#define R600_HDMI_UNKNOWN_0             0x0C
+#define R600_HDMI_AUDIOCNTL             0x10
+#define R600_HDMI_VIDEOCNTL             0x14
+#define R600_HDMI_VERSION               0x18
+#define R600_HDMI_UNKNOWN_1             0x28
+#define R600_HDMI_VIDEOINFOFRAME_0      0x54
+#define R600_HDMI_VIDEOINFOFRAME_1      0x58
+#define R600_HDMI_VIDEOINFOFRAME_2      0x5c
+#define R600_HDMI_VIDEOINFOFRAME_3      0x60
+#define R600_HDMI_32kHz_CTS             0xac
+#define R600_HDMI_32kHz_N               0xb0
+#define R600_HDMI_44_1kHz_CTS           0xb4
+#define R600_HDMI_44_1kHz_N             0xb8
+#define R600_HDMI_48kHz_CTS             0xbc
+#define R600_HDMI_48kHz_N               0xc0
+#define R600_HDMI_AUDIOINFOFRAME_0      0xcc
+#define R600_HDMI_AUDIOINFOFRAME_1      0xd0
+#define R600_HDMI_IEC60958_1            0xd4
+#define R600_HDMI_IEC60958_2            0xd8
+#define R600_HDMI_UNKNOWN_2             0xdc
+#define R600_HDMI_AUDIO_DEBUG_0         0xe0
+#define R600_HDMI_AUDIO_DEBUG_1         0xe4
+#define R600_HDMI_AUDIO_DEBUG_2         0xe8
+#define R600_HDMI_AUDIO_DEBUG_3         0xec
 
 /* HDMI additional config base register addresses */
 #define R600_HDMI_CONFIG1                 0x7600
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 5baf7fd..1fefd2b 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -375,6 +375,8 @@ struct radeon_irq {
 	wait_queue_head_t	vblank_queue;
 	/* FIXME: use defines for max hpd/dacs */
 	bool            hpd[6];
+	/* FIXME: use defines for max HDMI blocks */
+	bool		hdmi[2];
 	spinlock_t sw_lock;
 	int sw_refcount;
 };
@@ -1292,6 +1294,7 @@ extern int r600_audio_bits_per_sample(struct radeon_device *rdev);
 extern int r600_audio_rate(struct radeon_device *rdev);
 extern uint8_t r600_audio_status_bits(struct radeon_device *rdev);
 extern uint8_t r600_audio_category_code(struct radeon_device *rdev);
+extern void r600_audio_schedule_polling(struct radeon_device *rdev);
 extern void r600_audio_enable_polling(struct drm_encoder *encoder);
 extern void r600_audio_disable_polling(struct drm_encoder *encoder);
 extern void r600_audio_fini(struct radeon_device *rdev);
-- 
1.7.0

------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to