Skip to contentSkip to conversation

Implement IRQ support for HDMI audio

PATCH New Christian König 2 participants 3 messages Apr 10, 2010 – Apr 23, 2010 4 messages not in the archive

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Implement IRQ support for HDMI audio

Hi,

the attached two patches get rid of the polling timer for HDMI audio updates in the radeon driver by implementing the proper IRQ support for format change notifications.

Those were tested only on an RV630 chipset, and I expected that they need some more love for other chipset generations. So guys please test and review them, as always feedbacks would be very welcome.

Christian.

Quoted 1 line

From 1394315e3a82e342219c52b2a4d27cc43513c061 Mon Sep 17 00:00:00 2001

From: =?UTF-8?q?Christian=20K=C3=B6nig?= <[email protected]>
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.

---
 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(-)
drivers/gpu/drm/radeon/r600_audio.c +41 -14
index dac7042..03bf8bc 100644
@@ -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;
 }
 
 /*
drivers/gpu/drm/radeon/r600_hdmi.c +11 -6
index 029fa14..1960ac3 100644
@@ -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);
 
drivers/gpu/drm/radeon/radeon.h +8 -6
index 034218c..5baf7fd 100644
@@ -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 {
drivers/gpu/drm/radeon/radeon_mode.h +1 -0
index 0b8e327..715bfb7 100644
@@ -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;
Signature · 1 line
1.7.0
Quoted 1 line

From 88ca304ef749e66961e11ee1e258ea1e001e471f Mon Sep 17 00:00:00 2001

From: Christian Koenig <[email protected]>
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.

---
 drivers/gpu/drm/radeon/r600.c       |    6 ++++
 drivers/gpu/drm/radeon/r600_audio.c |   20 +++++++++----
 drivers/gpu/drm/radeon/r600_hdmi.c  |   56 ++++++++++++++++++++++++----------
 drivers/gpu/drm/radeon/radeon.h     |    2 +
 4 files changed, 61 insertions(+), 23 deletions(-)
drivers/gpu/drm/radeon/r600.c +6 -0
index 8f3454e..a275728 100644
@@ -2713,6 +2713,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 +2854,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 */
drivers/gpu/drm/radeon/r600_audio.c +14 -6
index 03bf8bc..487b56b 100644
@@ -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,15 @@ 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))
+		int irq_pending = r600_hdmi_irq_pending(encoder);
+		if (irq_pending || radeon_encoder->audio_polling_active) {
+			still_going |= radeon_encoder->audio_polling_active;
+			if (irq_pending || 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);
 }
 
 /*
drivers/gpu/drm/radeon/r600_hdmi.c +39 -17

104 lines not on this page · raw message

drivers/gpu/drm/radeon/radeon.h +2 -0
index 5baf7fd..fca8e9e 100644
@@ -1292,6 +1292,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);
@@ -1300,6 +1301,7 @@ 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 int r600_hdmi_irq_pending(struct drm_encoder *encoder);
 extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
 
 /* evergreen */
Signature · 1 line
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/dri-devel

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): 1271115105.2296.2.camel@zweiundvierzig

A message that is not in the archive (sent off-list or not yet received): [email protected]

#5 lore raw

PATCH 1/1 Implement IRQ support for HDMI audio (Ver 2)

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.

Quoted 1 line

From cc9ec18c9e31b1bd0ca19b5729ffed1e3b4a6e2d Mon Sep 17 00:00:00 2001

From: =?UTF-8?q?Christian=20K=C3=B6nig?= <[email protected]>
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.

---
 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(-)
drivers/gpu/drm/radeon/r600_audio.c +41 -14
index dac7042..03bf8bc 100644
@@ -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;
 }
 
 /*
drivers/gpu/drm/radeon/r600_hdmi.c +11 -6
index 029fa14..1960ac3 100644
@@ -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);
 
drivers/gpu/drm/radeon/radeon.h +8 -6
index 034218c..5baf7fd 100644
@@ -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 {
drivers/gpu/drm/radeon/radeon_mode.h +1 -0
index 0b8e327..715bfb7 100644
@@ -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;
Signature · 1 line
1.7.0
Quoted 1 line

From 1658a5093ee03b951738ac376a3fafb5707d279b Mon Sep 17 00:00:00 2001

From: Christian Koenig <[email protected]>
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.

---
 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(-)
drivers/gpu/drm/radeon/r600.c +33 -0
index 8f3454e..421b485 100644
@@ -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 */
drivers/gpu/drm/radeon/r600_audio.c +13 -8
index 03bf8bc..89d8dc9 100644
@@ -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);
 }
 
 /*
drivers/gpu/drm/radeon/r600_hdmi.c +32 -21

111 lines not on this page · raw message

drivers/gpu/drm/radeon/r600_reg.h +30 -27

63 lines not on this page · raw message

drivers/gpu/drm/radeon/radeon.h +3 -0
index 5baf7fd..1fefd2b 100644
@@ -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);
Signature · 1 line
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/dri-devel

#6 lore raw

Re: [PATCH] Implement IRQ support for HDMI audio (Ver 2)

2010/4/13 Christian König <[email protected]>:

Quoted 9 lines

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.

It works fine for my RV620 :) As expected, I don't get "No signal" anymore on my A/V received after stopping playback. It seems to simply receive "empty" HDMI signal.

That's because we do not clean HDMI info after stopping and it's fine AFAIU. Of course starting next playback (even with different format) generates IRQ and works great.

Thanks for this great optimization! :)

Signature · 8 lines
Rafał

------------------------------------------------------------------------------
--
_______________________________________________
Dri-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/dri-devel