Skip to content

Commit

Permalink
drm/radeon/kms: rework audio polling timer
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Christian König authored and Dave Airlie committed Apr 23, 2010
1 parent 61cf059 commit 58bd086
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 26 deletions.
55 changes: 41 additions & 14 deletions drivers/gpu/drm/radeon/r600_audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ 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;
}

/*
* 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) {
Expand All @@ -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;
Expand All @@ -90,15 +90,15 @@ 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;
}

/*
* 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;
}
Expand All @@ -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;
Expand All @@ -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));
}

/*
Expand Down Expand Up @@ -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;
}

/*
Expand Down
17 changes: 11 additions & 6 deletions drivers/gpu/drm/radeon/r600_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);

Expand Down
14 changes: 8 additions & 6 deletions drivers/gpu/drm/radeon/radeon.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/radeon/radeon_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 58bd086

Please sign in to comment.