29,7 → 29,28 |
#include "radeon_asic.h" |
#include "atom.h" |
|
#define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */ |
/* |
* check if enc_priv stores radeon_encoder_atom_dig |
*/ |
static bool radeon_dig_encoder(struct drm_encoder *encoder) |
{ |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
switch (radeon_encoder->encoder_id) { |
case ENCODER_OBJECT_ID_INTERNAL_LVDS: |
case ENCODER_OBJECT_ID_INTERNAL_TMDS1: |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: |
case ENCODER_OBJECT_ID_INTERNAL_LVTM1: |
case ENCODER_OBJECT_ID_INTERNAL_DVO1: |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: |
case ENCODER_OBJECT_ID_INTERNAL_DDI: |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: |
return true; |
} |
return false; |
} |
|
/* |
* check if the chipset is supported |
36,115 → 57,91 |
*/ |
static int r600_audio_chipset_supported(struct radeon_device *rdev) |
{ |
return (rdev->family >= CHIP_R600 && rdev->family < CHIP_CEDAR) |
return (rdev->family >= CHIP_R600 && !ASIC_IS_DCE6(rdev)) |
|| rdev->family == CHIP_RS600 |
|| rdev->family == CHIP_RS690 |
|| rdev->family == CHIP_RS740; |
} |
|
/* |
* current number of channels |
*/ |
int r600_audio_channels(struct radeon_device *rdev) |
struct r600_audio r600_audio_status(struct radeon_device *rdev) |
{ |
return (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0x7) + 1; |
} |
struct r600_audio status; |
uint32_t value; |
|
/* |
* current bits per sample |
*/ |
int r600_audio_bits_per_sample(struct radeon_device *rdev) |
{ |
uint32_t value = (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0xF0) >> 4; |
switch (value) { |
case 0x0: return 8; |
case 0x1: return 16; |
case 0x2: return 20; |
case 0x3: return 24; |
case 0x4: return 32; |
} |
value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); |
|
dev_err(rdev->dev, "Unknown bits per sample 0x%x using 16 instead\n", |
/* number of channels */ |
status.channels = (value & 0x7) + 1; |
|
/* bits per sample */ |
switch ((value & 0xF0) >> 4) { |
case 0x0: |
status.bits_per_sample = 8; |
break; |
case 0x1: |
status.bits_per_sample = 16; |
break; |
case 0x2: |
status.bits_per_sample = 20; |
break; |
case 0x3: |
status.bits_per_sample = 24; |
break; |
case 0x4: |
status.bits_per_sample = 32; |
break; |
default: |
dev_err(rdev->dev, "Unknown bits per sample 0x%x, using 16\n", |
(int)value); |
|
return 16; |
status.bits_per_sample = 16; |
} |
|
/* |
* current sampling rate in HZ |
*/ |
int r600_audio_rate(struct radeon_device *rdev) |
{ |
uint32_t value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); |
uint32_t result; |
|
/* current sampling rate in HZ */ |
if (value & 0x4000) |
result = 44100; |
status.rate = 44100; |
else |
result = 48000; |
status.rate = 48000; |
status.rate *= ((value >> 11) & 0x7) + 1; |
status.rate /= ((value >> 8) & 0x7) + 1; |
|
result *= ((value >> 11) & 0x7) + 1; |
result /= ((value >> 8) & 0x7) + 1; |
value = RREG32(R600_AUDIO_STATUS_BITS); |
|
return result; |
} |
/* iec 60958 status bits */ |
status.status_bits = value & 0xff; |
|
/* |
* iec 60958 status bits |
*/ |
uint8_t r600_audio_status_bits(struct radeon_device *rdev) |
{ |
return RREG32(R600_AUDIO_STATUS_BITS) & 0xff; |
} |
/* iec 60958 category code */ |
status.category_code = (value >> 8) & 0xff; |
|
/* |
* iec 60958 category code |
*/ |
uint8_t r600_audio_category_code(struct radeon_device *rdev) |
{ |
return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff; |
return status; |
} |
|
/* |
* update all hdmi interfaces with current audio parameters |
*/ |
static void r600_audio_update_hdmi(unsigned long param) |
void r600_audio_update_hdmi(struct work_struct *work) |
{ |
struct radeon_device *rdev = (struct radeon_device *)param; |
struct radeon_device *rdev = container_of(work, struct radeon_device, |
audio_work); |
struct drm_device *dev = rdev->ddev; |
|
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); |
|
struct r600_audio audio_status = r600_audio_status(rdev); |
struct drm_encoder *encoder; |
int changes = 0, still_going = 0; |
bool changed = false; |
|
changes |= channels != rdev->audio_channels; |
changes |= rate != rdev->audio_rate; |
changes |= bps != rdev->audio_bits_per_sample; |
changes |= status_bits != rdev->audio_status_bits; |
changes |= category_code != rdev->audio_category_code; |
|
if (changes) { |
rdev->audio_channels = channels; |
rdev->audio_rate = rate; |
rdev->audio_bits_per_sample = bps; |
rdev->audio_status_bits = status_bits; |
rdev->audio_category_code = category_code; |
if (rdev->audio_status.channels != audio_status.channels || |
rdev->audio_status.rate != audio_status.rate || |
rdev->audio_status.bits_per_sample != audio_status.bits_per_sample || |
rdev->audio_status.status_bits != audio_status.status_bits || |
rdev->audio_status.category_code != audio_status.category_code) { |
rdev->audio_status = audio_status; |
changed = true; |
} |
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
still_going |= radeon_encoder->audio_polling_active; |
if (changes || r600_hdmi_buffer_status_changed(encoder)) |
if (!radeon_dig_encoder(encoder)) |
continue; |
if (changed || r600_hdmi_buffer_status_changed(encoder)) |
r600_hdmi_update_audio_settings(encoder); |
} |
|
// mod_timer(&rdev->audio_timer, |
// jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL)); |
} |
|
/* |
152,13 → 149,23 |
*/ |
static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable) |
{ |
u32 value = 0; |
DRM_INFO("%s audio support\n", enable ? "Enabling" : "Disabling"); |
WREG32_P(R600_AUDIO_ENABLE, enable ? 0x81000000 : 0x0, ~0x81000000); |
if (ASIC_IS_DCE4(rdev)) { |
if (enable) { |
value |= 0x81000000; /* Required to enable audio */ |
value |= 0x0e1000f0; /* fglrx sets that too */ |
} |
WREG32(EVERGREEN_AUDIO_ENABLE, value); |
} else { |
WREG32_P(R600_AUDIO_ENABLE, |
enable ? 0x81000000 : 0x0, ~0x81000000); |
} |
rdev->audio_enabled = enable; |
} |
|
/* |
* initialize the audio vars and register the update timer |
* initialize the audio vars |
*/ |
int r600_audio_init(struct radeon_device *rdev) |
{ |
167,19 → 174,12 |
|
r600_audio_engine_enable(rdev, true); |
|
rdev->audio_channels = -1; |
rdev->audio_rate = -1; |
rdev->audio_bits_per_sample = -1; |
rdev->audio_status_bits = 0; |
rdev->audio_category_code = 0; |
rdev->audio_status.channels = -1; |
rdev->audio_status.rate = -1; |
rdev->audio_status.bits_per_sample = -1; |
rdev->audio_status.status_bits = 0; |
rdev->audio_status.category_code = 0; |
|
// setup_timer( |
// &rdev->audio_timer, |
// r600_audio_update_hdmi, |
// (unsigned long)rdev); |
|
// mod_timer(&rdev->audio_timer, jiffies + 1); |
|
return 0; |
} |
|
192,6 → 192,7 |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); |
int base_rate = 48000; |
|
switch (radeon_encoder->encoder_id) { |
211,6 → 212,15 |
return; |
} |
|
if (ASIC_IS_DCE4(rdev)) { |
/* TODO: other PLLs? */ |
WREG32(EVERGREEN_AUDIO_PLL1_MUL, base_rate * 10); |
WREG32(EVERGREEN_AUDIO_PLL1_DIV, clock * 10); |
WREG32(EVERGREEN_AUDIO_PLL1_UNK, 0x00000071); |
|
/* Select DTO source */ |
WREG32(0x5ac, radeon_crtc->crtc_id); |
} else { |
switch (dig->dig_encoder) { |
case 0: |
WREG32(R600_AUDIO_PLL1_MUL, base_rate * 50); |
224,11 → 234,13 |
WREG32(R600_AUDIO_CLK_SRCSEL, 1); |
break; |
default: |
dev_err(rdev->dev, "Unsupported DIG on encoder 0x%02X\n", |
dev_err(rdev->dev, |
"Unsupported DIG on encoder 0x%02X\n", |
radeon_encoder->encoder_id); |
return; |
} |
} |
} |
|
/* |
* release the audio timer |
239,7 → 251,5 |
if (!rdev->audio_enabled) |
return; |
|
// del_timer(&rdev->audio_timer); |
|
r600_audio_engine_enable(rdev, false); |
} |