drm/radeon/kms: rework audio polling timer
authorChristian König <deathsimple@vodafone.de>
Mon, 5 Apr 2010 20:14:55 +0000 (22:14 +0200)
committerDave Airlie <airlied@redhat.com>
Fri, 23 Apr 2010 04:11:17 +0000 (14:11 +1000)
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 <deathsimple@vodafone.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/radeon/r600_audio.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_mode.h

index 1d89805..ed8d398 100644 (file)
@@ -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;
 }
 
 /*
index 2616b82..d014472 100644 (file)
@@ -353,17 +353,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)
@@ -518,6 +519,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);
 }
@@ -539,6 +542,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);
 
index e912098..42217af 100644 (file)
@@ -1327,18 +1327,20 @@ extern void r600_rlc_stop(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);
 
 extern void r700_cp_stop(struct radeon_device *rdev);
 extern void r700_cp_fini(struct radeon_device *rdev);
index 4a086c0..dd451c5 100644 (file)
@@ -345,6 +345,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;