Commit 58bd0863 authored by Christian König's avatar Christian König Committed by Dave Airlie

drm/radeon/kms: rework audio polling timer

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: default avatarChristian König <deathsimple@vodafone.de>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 61cf0593
...@@ -44,7 +44,7 @@ static int r600_audio_chipset_supported(struct radeon_device *rdev) ...@@ -44,7 +44,7 @@ static int r600_audio_chipset_supported(struct radeon_device *rdev)
/* /*
* current number of channels * 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; return (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0x7) + 1;
} }
...@@ -52,7 +52,7 @@ static int r600_audio_channels(struct radeon_device *rdev) ...@@ -52,7 +52,7 @@ static int r600_audio_channels(struct radeon_device *rdev)
/* /*
* current bits per sample * 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; uint32_t value = (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0xF0) >> 4;
switch (value) { switch (value) {
...@@ -71,7 +71,7 @@ static int r600_audio_bits_per_sample(struct radeon_device *rdev) ...@@ -71,7 +71,7 @@ static int r600_audio_bits_per_sample(struct radeon_device *rdev)
/* /*
* current sampling rate in HZ * 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 value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL);
uint32_t result; uint32_t result;
...@@ -90,7 +90,7 @@ static int r600_audio_rate(struct radeon_device *rdev) ...@@ -90,7 +90,7 @@ static int r600_audio_rate(struct radeon_device *rdev)
/* /*
* iec 60958 status bits * 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; return RREG32(R600_AUDIO_STATUS_BITS) & 0xff;
} }
...@@ -98,7 +98,7 @@ static uint8_t r600_audio_status_bits(struct radeon_device *rdev) ...@@ -98,7 +98,7 @@ static uint8_t r600_audio_status_bits(struct radeon_device *rdev)
/* /*
* iec 60958 category code * 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; return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff;
} }
...@@ -118,7 +118,7 @@ static void r600_audio_update_hdmi(unsigned long param) ...@@ -118,7 +118,7 @@ static void r600_audio_update_hdmi(unsigned long param)
uint8_t category_code = r600_audio_category_code(rdev); uint8_t category_code = r600_audio_category_code(rdev);
struct drm_encoder *encoder; struct drm_encoder *encoder;
int changes = 0; int changes = 0, still_going = 0;
changes |= channels != rdev->audio_channels; changes |= channels != rdev->audio_channels;
changes |= rate != rdev->audio_rate; changes |= rate != rdev->audio_rate;
...@@ -135,13 +135,15 @@ static void r600_audio_update_hdmi(unsigned long param) ...@@ -135,13 +135,15 @@ static void r600_audio_update_hdmi(unsigned long param)
} }
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 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)) if (changes || r600_hdmi_buffer_status_changed(encoder))
r600_hdmi_update_audio_settings( r600_hdmi_update_audio_settings(encoder);
encoder, channels, }
rate, bps, status_bits,
category_code);
} }
if(still_going)
mod_timer(&rdev->audio_timer, mod_timer(&rdev->audio_timer,
jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL)); jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL));
} }
...@@ -176,9 +178,34 @@ int r600_audio_init(struct radeon_device *rdev) ...@@ -176,9 +178,34 @@ int r600_audio_init(struct radeon_device *rdev)
r600_audio_update_hdmi, r600_audio_update_hdmi,
(unsigned long)rdev); (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); 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;
} }
/* /*
......
...@@ -353,17 +353,18 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod ...@@ -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 * update settings with current parameters from audio engine
*/ */
void r600_hdmi_update_audio_settings(struct drm_encoder *encoder, void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
int channels,
int rate,
int bps,
uint8_t status_bits,
uint8_t category_code)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset; 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; uint32_t iec;
if (!offset) if (!offset)
...@@ -518,6 +519,8 @@ void r600_hdmi_enable(struct drm_encoder *encoder) ...@@ -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", DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n",
radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
} }
...@@ -539,6 +542,8 @@ void r600_hdmi_disable(struct drm_encoder *encoder) ...@@ -539,6 +542,8 @@ void r600_hdmi_disable(struct drm_encoder *encoder)
return; return;
} }
r600_audio_disable_polling(encoder);
DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n", DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n",
radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
......
...@@ -1327,18 +1327,20 @@ extern void r600_rlc_stop(struct radeon_device *rdev); ...@@ -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_init(struct radeon_device *rdev);
extern int r600_audio_tmds_index(struct drm_encoder *encoder); extern int r600_audio_tmds_index(struct drm_encoder *encoder);
extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock); 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_audio_fini(struct radeon_device *rdev);
extern void r600_hdmi_init(struct drm_encoder *encoder); extern void r600_hdmi_init(struct drm_encoder *encoder);
extern void r600_hdmi_enable(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_disable(struct drm_encoder *encoder);
extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); 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_buffer_status_changed(struct drm_encoder *encoder);
extern void r600_hdmi_update_audio_settings(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 r700_cp_stop(struct radeon_device *rdev); extern void r700_cp_stop(struct radeon_device *rdev);
extern void r700_cp_fini(struct radeon_device *rdev); extern void r700_cp_fini(struct radeon_device *rdev);
......
...@@ -345,6 +345,7 @@ struct radeon_encoder { ...@@ -345,6 +345,7 @@ struct radeon_encoder {
enum radeon_rmx_type rmx_type; enum radeon_rmx_type rmx_type;
struct drm_display_mode native_mode; struct drm_display_mode native_mode;
void *enc_priv; void *enc_priv;
int audio_polling_active;
int hdmi_offset; int hdmi_offset;
int hdmi_config_offset; int hdmi_config_offset;
int hdmi_audio_workaround; int hdmi_audio_workaround;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment