That's my patchset making use of gained knowledge and released regs names. This is generally just cleaning currect stuff, changing offsets to relative ones (so we can use official regs now).
This patch adds temp hack for Evergreen changing offset by 0x3d0. This may look a little ugly, but it's safe and will be removed anyway. It's here just to don't add regression in Evergreen support.
My plan is to make use of Alex's WIP patch and add new file/code for DCE4 (Evergreen). That will allow us to correctly use Evergreen regs and drop thet 0x3d0 trick.
Patchset tested on RV620 and HD6320 (so both: R6xx and Evergreen).
Rafał Miłecki (5): drm/radeon/kms: move audio params to separated struct drm/radeon/kms: get rid of hdmi_config_offset drm/radeon/kms: get rid of r600_hdmi_find_free_block drm/radeon/kms: keep HDMI state in separated variable drm/radeon/kms/hdmi: use relative offsets, official regs
drivers/gpu/drm/radeon/evergreen_reg.h | 2 - drivers/gpu/drm/radeon/r600.c | 28 +++--- drivers/gpu/drm/radeon/r600_audio.c | 34 ++++---- drivers/gpu/drm/radeon/r600_hdmi.c | 153 +++++++++++++------------------- drivers/gpu/drm/radeon/r600_reg.h | 41 --------- drivers/gpu/drm/radeon/r600d.h | 7 +- drivers/gpu/drm/radeon/radeon.h | 19 ++-- drivers/gpu/drm/radeon/radeon_mode.h | 2 +- 8 files changed, 109 insertions(+), 177 deletions(-)
Signed-off-by: Rafał Miłecki zajec5@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/radeon/r600_audio.c | 34 +++++++++++++++++----------------- drivers/gpu/drm/radeon/radeon.h | 19 ++++++++++--------- 2 files changed, 27 insertions(+), 26 deletions(-)
diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c index a7c06c3..b922a3c 100644 --- a/drivers/gpu/drm/radeon/r600_audio.c +++ b/drivers/gpu/drm/radeon/r600_audio.c @@ -120,18 +120,18 @@ void r600_audio_update_hdmi(struct work_struct *work) struct drm_encoder *encoder; int changes = 0;
- 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; + 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; + 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; }
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { @@ -157,7 +157,7 @@ static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable) WREG32_P(R600_AUDIO_ENABLE, enable ? 0x81000000 : 0x0, ~0x81000000); } - rdev->audio_enabled = enable; + rdev->audio.enabled = enable; }
/* @@ -170,11 +170,11 @@ int r600_audio_init(struct radeon_device *rdev)
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.channels = -1; + rdev->audio.rate = -1; + rdev->audio.bits_per_sample = -1; + rdev->audio.status_bits = 0; + rdev->audio.category_code = 0;
return 0; } @@ -243,7 +243,7 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock) */ void r600_audio_fini(struct radeon_device *rdev) { - if (!rdev->audio_enabled) + if (!rdev->audio.enabled) return;
r600_audio_engine_enable(rdev, false); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 566ca3b..610acee 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1114,6 +1114,15 @@ int radeon_pm_get_type_index(struct radeon_device *rdev, enum radeon_pm_state_type ps_type, int instance);
+struct r600_audio { + bool enabled; + int channels; + int rate; + int bits_per_sample; + u8 status_bits; + u8 category_code; +}; + /* * Benchmarking */ @@ -1559,15 +1568,7 @@ struct radeon_device { int num_crtc; /* number of crtcs */ struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */ struct mutex vram_mutex; - - /* audio stuff */ - bool audio_enabled; - int audio_channels; - int audio_rate; - int audio_bits_per_sample; - uint8_t audio_status_bits; - uint8_t audio_category_code; - + struct r600_audio audio; /* audio stuff */ struct notifier_block acpi_nb; /* only one userspace can use Hyperz features or CMASK at a time */ struct drm_file *hyperz_filp;
Signed-off-by: Rafał Miłecki zajec5@gmail.com --- drivers/gpu/drm/radeon/evergreen_reg.h | 2 -- drivers/gpu/drm/radeon/r600_hdmi.c | 14 ++++---------- drivers/gpu/drm/radeon/r600_reg.h | 6 ++---- drivers/gpu/drm/radeon/radeon_mode.h | 1 - 4 files changed, 6 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h index 96c10b3..8beac10 100644 --- a/drivers/gpu/drm/radeon/evergreen_reg.h +++ b/drivers/gpu/drm/radeon/evergreen_reg.h @@ -232,6 +232,4 @@ /* HDMI blocks at 0x7030, 0x7c30, 0x10830, 0x11430, 0x12030, 0x12c30 */ #define EVERGREEN_HDMI_BASE 0x7030
-#define EVERGREEN_HDMI_CONFIG_OFFSET 0xf0 - #endif diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 37ac1b0..06e273e 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -485,14 +485,9 @@ static void r600_hdmi_assign_block(struct drm_encoder *encoder) } radeon_encoder->hdmi_offset = EVERGREEN_HDMI_BASE + eg_offsets[dig->dig_encoder]; - radeon_encoder->hdmi_config_offset = radeon_encoder->hdmi_offset - + EVERGREEN_HDMI_CONFIG_OFFSET; } else if (ASIC_IS_DCE3(rdev)) { radeon_encoder->hdmi_offset = dig->dig_encoder ? R600_HDMI_BLOCK3 : R600_HDMI_BLOCK1; - if (ASIC_IS_DCE32(rdev)) - radeon_encoder->hdmi_config_offset = dig->dig_encoder ? - R600_HDMI_CONFIG2 : R600_HDMI_CONFIG1; } else if (rdev->family >= CHIP_R600 || rdev->family == CHIP_RS600 || rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { radeon_encoder->hdmi_offset = r600_hdmi_find_free_block(dev); @@ -525,9 +520,9 @@ void r600_hdmi_enable(struct drm_encoder *encoder) if (ASIC_IS_DCE5(rdev)) { /* TODO */ } else if (ASIC_IS_DCE4(rdev)) { - WREG32_P(radeon_encoder->hdmi_config_offset + 0xc, 0x1, ~0x1); + WREG32_P(radeon_encoder->hdmi_offset + EVERGREEN_AUDIO_PACKET_CNTL, 0x1, ~0x1); } else if (ASIC_IS_DCE32(rdev)) { - WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0x1, ~0x1); + WREG32_P(radeon_encoder->hdmi_offset + R600_HDMI_AUDIO_PACKET_CNTL, 0x1, ~0x1); } else if (ASIC_IS_DCE3(rdev)) { /* TODO */ } else if (rdev->family >= CHIP_R600) { @@ -588,9 +583,9 @@ void r600_hdmi_disable(struct drm_encoder *encoder) if (ASIC_IS_DCE5(rdev)) { /* TODO */ } else if (ASIC_IS_DCE4(rdev)) { - WREG32_P(radeon_encoder->hdmi_config_offset + 0xc, 0, ~0x1); + WREG32_P(radeon_encoder->hdmi_offset + EVERGREEN_AUDIO_PACKET_CNTL, 0, ~0x1); } else if (ASIC_IS_DCE32(rdev)) { - WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0, ~0x1); + WREG32_P(radeon_encoder->hdmi_offset + R600_HDMI_AUDIO_PACKET_CNTL, 0, ~0x1); } else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: @@ -610,5 +605,4 @@ void r600_hdmi_disable(struct drm_encoder *encoder) }
radeon_encoder->hdmi_offset = 0; - radeon_encoder->hdmi_config_offset = 0; } diff --git a/drivers/gpu/drm/radeon/r600_reg.h b/drivers/gpu/drm/radeon/r600_reg.h index f869897..24c9412 100644 --- a/drivers/gpu/drm/radeon/r600_reg.h +++ b/drivers/gpu/drm/radeon/r600_reg.h @@ -192,9 +192,7 @@ #define R600_HDMI_AUDIO_DEBUG_1 0xe4 #define R600_HDMI_AUDIO_DEBUG_2 0xe8 #define R600_HDMI_AUDIO_DEBUG_3 0xec - -/* HDMI additional config base register addresses */ -#define R600_HDMI_CONFIG1 0x7600 -#define R600_HDMI_CONFIG2 0x7a00 +#define R600_HDMI_AUDIO_PACKET_CNTL 0x204 +#define EVERGREEN_AUDIO_PACKET_CNTL 0xfc
#endif diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index b2cca6a..228b381 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -385,7 +385,6 @@ struct radeon_encoder { void *enc_priv; int audio_polling_active; int hdmi_offset; - int hdmi_config_offset; int hdmi_audio_workaround; int hdmi_buffer_status; bool is_ext_encoder;
R6xx has routable blocks, but there's nothing wrong in assignment based on dig_encoder. We didn't really need that algorithm.
Signed-off-by: Rafał Miłecki zajec5@gmail.com --- drivers/gpu/drm/radeon/r600_hdmi.c | 45 ++++++----------------------------- 1 files changed, 8 insertions(+), 37 deletions(-)
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 06e273e..834ca02 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -421,40 +421,6 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder) r600_hdmi_audio_workaround(encoder); }
-static int r600_hdmi_find_free_block(struct drm_device *dev) -{ - struct radeon_device *rdev = dev->dev_private; - struct drm_encoder *encoder; - struct radeon_encoder *radeon_encoder; - bool free_blocks[3] = { true, true, true }; - - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - radeon_encoder = to_radeon_encoder(encoder); - switch (radeon_encoder->hdmi_offset) { - case R600_HDMI_BLOCK1: - free_blocks[0] = false; - break; - case R600_HDMI_BLOCK2: - free_blocks[1] = false; - break; - case R600_HDMI_BLOCK3: - free_blocks[2] = false; - break; - } - } - - if (rdev->family == CHIP_RS600 || rdev->family == CHIP_RS690 || - rdev->family == CHIP_RS740) { - return free_blocks[0] ? R600_HDMI_BLOCK1 : 0; - } else if (rdev->family >= CHIP_R600) { - if (free_blocks[0]) - return R600_HDMI_BLOCK1; - else if (free_blocks[1]) - return R600_HDMI_BLOCK2; - } - return 0; -} - static void r600_hdmi_assign_block(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; @@ -488,9 +454,14 @@ static void r600_hdmi_assign_block(struct drm_encoder *encoder) } else if (ASIC_IS_DCE3(rdev)) { radeon_encoder->hdmi_offset = dig->dig_encoder ? R600_HDMI_BLOCK3 : R600_HDMI_BLOCK1; - } else if (rdev->family >= CHIP_R600 || rdev->family == CHIP_RS600 || - rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { - radeon_encoder->hdmi_offset = r600_hdmi_find_free_block(dev); + } else if (rdev->family >= CHIP_R600) { + /* 2 routable blocks, but using dig_encoder should be fine */ + radeon_encoder->hdmi_offset = dig->dig_encoder ? + R600_HDMI_BLOCK2 : R600_HDMI_BLOCK1; + } else if (rdev->family == CHIP_RS600 || rdev->family == CHIP_RS690 || + rdev->family == CHIP_RS740) { + /* Only 1 routable block */ + radeon_encoder->hdmi_offset = R600_HDMI_BLOCK1; } }
If we want hdmi_offset to be relative to the first block, zero value can be used also for enabled block.
Signed-off-by: Rafał Miłecki zajec5@gmail.com --- drivers/gpu/drm/radeon/r600_hdmi.c | 16 +++++++++------- drivers/gpu/drm/radeon/radeon_mode.h | 1 + 2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 834ca02..ba3b65c 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -275,7 +275,7 @@ int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder) struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); int status, result;
- if (!radeon_encoder->hdmi_offset) + if (!radeon_encoder->hdmi_enabled) return 0;
status = r600_hdmi_is_audio_buffer_filled(encoder); @@ -295,7 +295,7 @@ void r600_hdmi_audio_workaround(struct drm_encoder *encoder) struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); uint32_t offset = radeon_encoder->hdmi_offset;
- if (!offset) + if (!radeon_encoder->hdmi_enabled) return;
if (!radeon_encoder->hdmi_audio_workaround || @@ -323,7 +323,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod if (ASIC_IS_DCE5(rdev)) return;
- if (!offset) + if (!to_radeon_encoder(encoder)->hdmi_enabled) return;
r600_audio_set_clock(encoder, mode->clock); @@ -370,7 +370,7 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
uint32_t iec;
- if (!offset) + if (!to_radeon_encoder(encoder)->hdmi_enabled) return;
DRM_DEBUG("%s with %d channels, %d Hz sampling rate, %d bits per sample,\n", @@ -463,6 +463,7 @@ static void r600_hdmi_assign_block(struct drm_encoder *encoder) /* Only 1 routable block */ radeon_encoder->hdmi_offset = R600_HDMI_BLOCK1; } + radeon_encoder->hdmi_enabled = true; }
/* @@ -478,9 +479,9 @@ void r600_hdmi_enable(struct drm_encoder *encoder) if (ASIC_IS_DCE5(rdev)) return;
- if (!radeon_encoder->hdmi_offset) { + if (!radeon_encoder->hdmi_enabled) { r600_hdmi_assign_block(encoder); - if (!radeon_encoder->hdmi_offset) { + if (!radeon_encoder->hdmi_enabled) { dev_warn(rdev->dev, "Could not find HDMI block for " "0x%x encoder\n", radeon_encoder->encoder_id); return; @@ -538,7 +539,7 @@ void r600_hdmi_disable(struct drm_encoder *encoder) return;
offset = radeon_encoder->hdmi_offset; - if (!offset) { + if (!radeon_encoder->hdmi_enabled) { dev_err(rdev->dev, "Disabling not enabled HDMI\n"); return; } @@ -575,5 +576,6 @@ void r600_hdmi_disable(struct drm_encoder *encoder) } }
+ radeon_encoder->hdmi_enabled = false; radeon_encoder->hdmi_offset = 0; } diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 228b381..0c3cdbd 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -384,6 +384,7 @@ struct radeon_encoder { struct drm_display_mode native_mode; void *enc_priv; int audio_polling_active; + bool hdmi_enabled; int hdmi_offset; int hdmi_audio_workaround; int hdmi_buffer_status;
Signed-off-by: Rafał Miłecki zajec5@gmail.com --- drivers/gpu/drm/radeon/r600.c | 28 ++++++------ drivers/gpu/drm/radeon/r600_hdmi.c | 90 +++++++++++++++++++----------------- drivers/gpu/drm/radeon/r600_reg.h | 39 --------------- drivers/gpu/drm/radeon/r600d.h | 7 ++- 4 files changed, 66 insertions(+), 98 deletions(-)
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index ba637d9..8f84bd6 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2968,10 +2968,10 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev) WREG32(DC_HPD5_INT_CONTROL, tmp); tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY; WREG32(DC_HPD6_INT_CONTROL, tmp); - tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; - WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0, tmp); - tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; - WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1, tmp); + tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; + WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0, tmp); + tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; + WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1, tmp); } else { tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); @@ -3110,8 +3110,8 @@ int r600_irq_set(struct radeon_device *rdev) if (ASIC_IS_DCE32(rdev)) { hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; - hdmi0 = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0) & ~AFMT_AZ_FORMAT_WTRIG_MASK; - hdmi1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1) & ~AFMT_AZ_FORMAT_WTRIG_MASK; + hdmi0 = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0) & ~AFMT_AZ_FORMAT_WTRIG_MASK; + hdmi1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1) & ~AFMT_AZ_FORMAT_WTRIG_MASK; } else { hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; hdmi1 = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; @@ -3189,8 +3189,8 @@ int r600_irq_set(struct radeon_device *rdev) if (ASIC_IS_DCE32(rdev)) { WREG32(DC_HPD5_INT_CONTROL, hpd5); WREG32(DC_HPD6_INT_CONTROL, hpd6); - WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0, hdmi0); - WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1, hdmi1); + WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0, hdmi0); + WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1, hdmi1); } else { WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0); WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, hdmi1); @@ -3215,8 +3215,8 @@ static void r600_irq_ack(struct radeon_device *rdev) rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE); rdev->irq.stat_regs.r600.disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2); if (ASIC_IS_DCE32(rdev)) { - rdev->irq.stat_regs.r600.hdmi0_status = RREG32(AFMT_STATUS + HDMI_OFFSET0); - rdev->irq.stat_regs.r600.hdmi1_status = RREG32(AFMT_STATUS + HDMI_OFFSET1); + rdev->irq.stat_regs.r600.hdmi0_status = RREG32(AFMT_STATUS + DCE3_HDMI_OFFSET0); + rdev->irq.stat_regs.r600.hdmi1_status = RREG32(AFMT_STATUS + DCE3_HDMI_OFFSET1); } else { rdev->irq.stat_regs.r600.hdmi0_status = RREG32(HDMI0_STATUS); rdev->irq.stat_regs.r600.hdmi1_status = RREG32(DCE3_HDMI1_STATUS); @@ -3293,14 +3293,14 @@ static void r600_irq_ack(struct radeon_device *rdev) WREG32(DC_HPD6_INT_CONTROL, tmp); } if (rdev->irq.stat_regs.r600.hdmi0_status & AFMT_AZ_FORMAT_WTRIG) { - tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0); + tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0); tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; - WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0, tmp); + WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0, tmp); } if (rdev->irq.stat_regs.r600.hdmi1_status & AFMT_AZ_FORMAT_WTRIG) { - tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1); + tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1); tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; - WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1, tmp); + WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1, tmp); } } else { if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) { diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index ba3b65c..c6de0022 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -27,6 +27,7 @@ #include "radeon_drm.h" #include "radeon.h" #include "radeon_asic.h" +#include "r600d.h" #include "atom.h"
/* @@ -108,20 +109,20 @@ static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock) CTS = r600_hdmi_ACR[i].CTS_32kHz; N = r600_hdmi_ACR[i].N_32kHz; r600_hdmi_calc_CTS(clock, &CTS, N, 32000); - WREG32(offset+R600_HDMI_32kHz_CTS, CTS << 12); - WREG32(offset+R600_HDMI_32kHz_N, N); + WREG32(HDMI0_ACR_32_0 + offset, HDMI0_ACR_CTS_32(CTS)); + WREG32(HDMI0_ACR_32_1 + offset, N);
CTS = r600_hdmi_ACR[i].CTS_44_1kHz; N = r600_hdmi_ACR[i].N_44_1kHz; r600_hdmi_calc_CTS(clock, &CTS, N, 44100); - WREG32(offset+R600_HDMI_44_1kHz_CTS, CTS << 12); - WREG32(offset+R600_HDMI_44_1kHz_N, N); + WREG32(HDMI0_ACR_44_0 + offset, HDMI0_ACR_CTS_44(CTS)); + WREG32(HDMI0_ACR_44_1 + offset, N);
CTS = r600_hdmi_ACR[i].CTS_48kHz; N = r600_hdmi_ACR[i].N_48kHz; r600_hdmi_calc_CTS(clock, &CTS, N, 48000); - WREG32(offset+R600_HDMI_48kHz_CTS, CTS << 12); - WREG32(offset+R600_HDMI_48kHz_N, N); + WREG32(HDMI0_ACR_48_0 + offset, HDMI0_ACR_CTS_48(CTS)); + WREG32(HDMI0_ACR_48_1 + offset, N); }
/* @@ -204,13 +205,13 @@ static void r600_hdmi_videoinfoframe( * workaround this issue. */ frame[0x0] += 2;
- WREG32(offset+R600_HDMI_VIDEOINFOFRAME_0, + WREG32(HDMI0_AVI_INFO0 + offset, frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); - WREG32(offset+R600_HDMI_VIDEOINFOFRAME_1, + WREG32(HDMI0_AVI_INFO1 + offset, frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x7] << 24)); - WREG32(offset+R600_HDMI_VIDEOINFOFRAME_2, + WREG32(HDMI0_AVI_INFO2 + offset, frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24)); - WREG32(offset+R600_HDMI_VIDEOINFOFRAME_3, + WREG32(HDMI0_AVI_INFO3 + offset, frame[0xC] | (frame[0xD] << 8)); }
@@ -249,9 +250,9 @@ static void r600_hdmi_audioinfoframe(
r600_hdmi_infoframe_checksum(0x84, 0x01, 0x0A, frame);
- WREG32(offset+R600_HDMI_AUDIOINFOFRAME_0, + WREG32(HDMI0_AUDIO_INFO0 + offset, frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); - WREG32(offset+R600_HDMI_AUDIOINFOFRAME_1, + WREG32(HDMI0_AUDIO_INFO1 + offset, frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x8] << 24)); }
@@ -264,7 +265,7 @@ static int r600_hdmi_is_audio_buffer_filled(struct drm_encoder *encoder) struct radeon_device *rdev = dev->dev_private; uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
- return (RREG32(offset+R600_HDMI_STATUS) & 0x10) != 0; + return (RREG32(HDMI0_STATUS + offset) & 0x10) != 0; }
/* @@ -302,11 +303,11 @@ void r600_hdmi_audio_workaround(struct drm_encoder *encoder) r600_hdmi_is_audio_buffer_filled(encoder)) {
/* disable audio workaround */ - WREG32_P(offset+R600_HDMI_CNTL, 0x00000001, ~0x00001001); + WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset, 0x0001, ~0x1001);
} else { /* enable audio workaround */ - WREG32_P(offset+R600_HDMI_CNTL, 0x00001001, ~0x00001001); + WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset, 0x1001, ~0x1001); } }
@@ -328,29 +329,29 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
r600_audio_set_clock(encoder, mode->clock);
- WREG32(offset+R600_HDMI_UNKNOWN_0, 0x1000); - WREG32(offset+R600_HDMI_UNKNOWN_1, 0x0); - WREG32(offset+R600_HDMI_UNKNOWN_2, 0x1000); + WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000); + WREG32(HDMI0_GC + offset, 0x0); + WREG32(HDMI0_ACR_PACKET_CONTROL + offset, 0x1000);
r600_hdmi_update_ACR(encoder, mode->clock);
- WREG32(offset+R600_HDMI_VIDEOCNTL, 0x13); + WREG32(HDMI0_INFOFRAME_CONTROL0 + offset, 0x13);
- WREG32(offset+R600_HDMI_VERSION, 0x202); + WREG32(HDMI0_INFOFRAME_CONTROL1 + offset, 0x202);
r600_hdmi_videoinfoframe(encoder, RGB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ - WREG32(offset+R600_HDMI_AUDIO_DEBUG_0, 0x00FFFFFF); - WREG32(offset+R600_HDMI_AUDIO_DEBUG_1, 0x007FFFFF); - WREG32(offset+R600_HDMI_AUDIO_DEBUG_2, 0x00000001); - WREG32(offset+R600_HDMI_AUDIO_DEBUG_3, 0x00000001); + WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF); + WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF); + WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001); + WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001);
r600_hdmi_audio_workaround(encoder);
/* audio packets per line, does anyone know how to calc this ? */ - WREG32_P(offset+R600_HDMI_CNTL, 0x00040000, ~0x001F0000); + WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset, 0x00040000, ~0x001F0000); }
/* @@ -401,7 +402,7 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder) case 192000: iec |= 0xe << 24; break; }
- WREG32(offset+R600_HDMI_IEC60958_1, iec); + WREG32(HDMI0_60958_0 + offset, iec);
iec = 0; switch (bps) { @@ -412,10 +413,10 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder) if (status_bits & AUDIO_STATUS_V) iec |= 0x5 << 16;
- WREG32_P(offset+R600_HDMI_IEC60958_2, iec, ~0x5000f); + WREG32_P(HDMI0_60958_1 + offset, iec, ~0x5000f);
/* 0x021 or 0x031 sets the audio frame length */ - WREG32(offset+R600_HDMI_AUDIOCNTL, 0x31); + WREG32(HDMI0_VBI_PACKET_CONTROL + offset, 0x31); r600_hdmi_audioinfoframe(encoder, channels-1, 0, 0, 0, 0, 0, 0, 0);
r600_hdmi_audio_workaround(encoder); @@ -449,19 +450,22 @@ static void r600_hdmi_assign_block(struct drm_encoder *encoder) dev_err(rdev->dev, "Enabling HDMI on unknown dig\n"); return; } - radeon_encoder->hdmi_offset = EVERGREEN_HDMI_BASE + - eg_offsets[dig->dig_encoder]; + radeon_encoder->hdmi_offset = eg_offsets[dig->dig_encoder]; + /* Temp hack for Evergreen until we split r600_hdmi.c + * Evergreen first block is 0x7030 instead of 0x7400. + */ + radeon_encoder->hdmi_offset -= 0x3d0; } else if (ASIC_IS_DCE3(rdev)) { radeon_encoder->hdmi_offset = dig->dig_encoder ? - R600_HDMI_BLOCK3 : R600_HDMI_BLOCK1; + DCE3_HDMI_OFFSET1 : DCE3_HDMI_OFFSET0; } else if (rdev->family >= CHIP_R600) { /* 2 routable blocks, but using dig_encoder should be fine */ radeon_encoder->hdmi_offset = dig->dig_encoder ? - R600_HDMI_BLOCK2 : R600_HDMI_BLOCK1; + DCE2_HDMI_OFFSET1 : DCE2_HDMI_OFFSET0; } else if (rdev->family == CHIP_RS600 || rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { /* Only 1 routable block */ - radeon_encoder->hdmi_offset = R600_HDMI_BLOCK1; + radeon_encoder->hdmi_offset = DCE2_HDMI_OFFSET0; } radeon_encoder->hdmi_enabled = true; } @@ -492,9 +496,9 @@ void r600_hdmi_enable(struct drm_encoder *encoder) if (ASIC_IS_DCE5(rdev)) { /* TODO */ } else if (ASIC_IS_DCE4(rdev)) { - WREG32_P(radeon_encoder->hdmi_offset + EVERGREEN_AUDIO_PACKET_CNTL, 0x1, ~0x1); + WREG32_P(0x74fc + radeon_encoder->hdmi_offset, 0x1, ~0x1); } else if (ASIC_IS_DCE32(rdev)) { - WREG32_P(radeon_encoder->hdmi_offset + R600_HDMI_AUDIO_PACKET_CNTL, 0x1, ~0x1); + WREG32_P(AFMT_AUDIO_PACKET_CONTROL + radeon_encoder->hdmi_offset, 0x1, ~0x1); } else if (ASIC_IS_DCE3(rdev)) { /* TODO */ } else if (rdev->family >= CHIP_R600) { @@ -502,12 +506,12 @@ void r600_hdmi_enable(struct drm_encoder *encoder) case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: WREG32_P(AVIVO_TMDSA_CNTL, AVIVO_TMDSA_CNTL_HDMI_EN, ~AVIVO_TMDSA_CNTL_HDMI_EN); - WREG32(offset + R600_HDMI_ENABLE, 0x101); + WREG32(HDMI0_CONTROL + offset, 0x101); break; case ENCODER_OBJECT_ID_INTERNAL_LVTM1: WREG32_P(AVIVO_LVTMA_CNTL, AVIVO_LVTMA_CNTL_HDMI_EN, ~AVIVO_LVTMA_CNTL_HDMI_EN); - WREG32(offset + R600_HDMI_ENABLE, 0x105); + WREG32(HDMI0_CONTROL + offset, 0x105); break; default: dev_err(rdev->dev, "Unknown HDMI output type\n"); @@ -517,7 +521,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
if (rdev->irq.installed) { /* if irq is available use it */ - rdev->irq.afmt[offset == R600_HDMI_BLOCK1 ? 0 : 1] = true; + rdev->irq.afmt[offset == 0 ? 0 : 1] = true; radeon_irq_set(rdev); }
@@ -548,27 +552,27 @@ void r600_hdmi_disable(struct drm_encoder *encoder) offset, radeon_encoder->encoder_id);
/* disable irq */ - rdev->irq.afmt[offset == R600_HDMI_BLOCK1 ? 0 : 1] = false; + rdev->irq.afmt[offset == 0 ? 0 : 1] = false; radeon_irq_set(rdev);
if (ASIC_IS_DCE5(rdev)) { /* TODO */ } else if (ASIC_IS_DCE4(rdev)) { - WREG32_P(radeon_encoder->hdmi_offset + EVERGREEN_AUDIO_PACKET_CNTL, 0, ~0x1); + WREG32_P(0x74fc + radeon_encoder->hdmi_offset, 0, ~0x1); } else if (ASIC_IS_DCE32(rdev)) { - WREG32_P(radeon_encoder->hdmi_offset + R600_HDMI_AUDIO_PACKET_CNTL, 0, ~0x1); + WREG32_P(AFMT_AUDIO_PACKET_CONTROL + radeon_encoder->hdmi_offset, 0, ~0x1); } else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: WREG32_P(AVIVO_TMDSA_CNTL, 0, ~AVIVO_TMDSA_CNTL_HDMI_EN); - WREG32(offset + R600_HDMI_ENABLE, 0); + WREG32(HDMI0_CONTROL + offset, 0); break; case ENCODER_OBJECT_ID_INTERNAL_LVTM1: WREG32_P(AVIVO_LVTMA_CNTL, 0, ~AVIVO_LVTMA_CNTL_HDMI_EN); - WREG32(offset + R600_HDMI_ENABLE, 0); + WREG32(HDMI0_CONTROL + offset, 0); break; default: dev_err(rdev->dev, "Unknown HDMI output type\n"); diff --git a/drivers/gpu/drm/radeon/r600_reg.h b/drivers/gpu/drm/radeon/r600_reg.h index 24c9412..c44304a 100644 --- a/drivers/gpu/drm/radeon/r600_reg.h +++ b/drivers/gpu/drm/radeon/r600_reg.h @@ -156,43 +156,4 @@ #define R600_AUDIO_PIN_WIDGET_CNTL 0x73d4 #define R600_AUDIO_STATUS_BITS 0x73d8
-/* HDMI base register addresses */ -#define R600_HDMI_BLOCK1 0x7400 -#define R600_HDMI_BLOCK2 0x7700 -#define R600_HDMI_BLOCK3 0x7800 - -/* HDMI registers */ -#define R600_HDMI_ENABLE 0x00 -#define R600_HDMI_STATUS 0x04 -# define R600_HDMI_INT_PENDING (1 << 29) -#define R600_HDMI_CNTL 0x08 -# define R600_HDMI_INT_EN (1 << 28) -# define R600_HDMI_INT_ACK (1 << 29) -#define R600_HDMI_UNKNOWN_0 0x0C -#define R600_HDMI_AUDIOCNTL 0x10 -#define R600_HDMI_VIDEOCNTL 0x14 -#define R600_HDMI_VERSION 0x18 -#define R600_HDMI_UNKNOWN_1 0x28 -#define R600_HDMI_VIDEOINFOFRAME_0 0x54 -#define R600_HDMI_VIDEOINFOFRAME_1 0x58 -#define R600_HDMI_VIDEOINFOFRAME_2 0x5c -#define R600_HDMI_VIDEOINFOFRAME_3 0x60 -#define R600_HDMI_32kHz_CTS 0xac -#define R600_HDMI_32kHz_N 0xb0 -#define R600_HDMI_44_1kHz_CTS 0xb4 -#define R600_HDMI_44_1kHz_N 0xb8 -#define R600_HDMI_48kHz_CTS 0xbc -#define R600_HDMI_48kHz_N 0xc0 -#define R600_HDMI_AUDIOINFOFRAME_0 0xcc -#define R600_HDMI_AUDIOINFOFRAME_1 0xd0 -#define R600_HDMI_IEC60958_1 0xd4 -#define R600_HDMI_IEC60958_2 0xd8 -#define R600_HDMI_UNKNOWN_2 0xdc -#define R600_HDMI_AUDIO_DEBUG_0 0xe0 -#define R600_HDMI_AUDIO_DEBUG_1 0xe4 -#define R600_HDMI_AUDIO_DEBUG_2 0xe8 -#define R600_HDMI_AUDIO_DEBUG_3 0xec -#define R600_HDMI_AUDIO_PACKET_CNTL 0x204 -#define EVERGREEN_AUDIO_PACKET_CNTL 0xfc - #endif diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 426e5a7..a9652be 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -1056,9 +1056,12 @@ # define AFMT_AZ_FORMAT_WTRIG_MASK (1 << 28) # define AFMT_AZ_FORMAT_WTRIG_ACK (1 << 29) # define AFMT_AZ_AUDIO_ENABLE_CHG_ACK (1 << 30) + +#define DCE2_HDMI_OFFSET0 (0x7400 - 0x7400) +#define DCE2_HDMI_OFFSET1 (0x7700 - 0x7400) /* DCE3.2 second instance starts at 0x7800 */ -#define HDMI_OFFSET0 (0x7400 - 0x7400) -#define HDMI_OFFSET1 (0x7800 - 0x7400) +#define DCE3_HDMI_OFFSET0 (0x7400 - 0x7400) +#define DCE3_HDMI_OFFSET1 (0x7800 - 0x7400)
/* * PM4
On 28.04.2012 23:35, Rafał Miłecki wrote:
That's my patchset making use of gained knowledge and released regs names. This is generally just cleaning currect stuff, changing offsets to relative ones (so we can use official regs now).
This patch adds temp hack for Evergreen changing offset by 0x3d0. This may look a little ugly, but it's safe and will be removed anyway. It's here just to don't add regression in Evergreen support.
My plan is to make use of Alex's WIP patch and add new file/code for DCE4 (Evergreen). That will allow us to correctly use Evergreen regs and drop thet 0x3d0 trick.
Patchset tested on RV620 and HD6320 (so both: R6xx and Evergreen).
Rafał Miłecki (5): drm/radeon/kms: move audio params to separated struct drm/radeon/kms: get rid of hdmi_config_offset drm/radeon/kms: get rid of r600_hdmi_find_free_block drm/radeon/kms: keep HDMI state in separated variable drm/radeon/kms/hdmi: use relative offsets, official regs
drivers/gpu/drm/radeon/evergreen_reg.h | 2 - drivers/gpu/drm/radeon/r600.c | 28 +++--- drivers/gpu/drm/radeon/r600_audio.c | 34 ++++---- drivers/gpu/drm/radeon/r600_hdmi.c | 153 +++++++++++++------------------- drivers/gpu/drm/radeon/r600_reg.h | 41 --------- drivers/gpu/drm/radeon/r600d.h | 7 +- drivers/gpu/drm/radeon/radeon.h | 19 ++-- drivers/gpu/drm/radeon/radeon_mode.h | 2 +- 8 files changed, 109 insertions(+), 177 deletions(-)
Looks good to me and also just tested on my RV710.
So both:
/Tested-by: //Christian König deathsimple@vodafone.de/ /Reviewed-by: Christian König deathsimple@vodafone.de ///
dri-devel@lists.freedesktop.org