dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [deathsimple/drm-next-3.16][PATCH V3 1/4] drm/radeon/hdmi: use separated file for DCE 3.1/3.2 code
@ 2014-05-16  9:10 Rafał Miłecki
  2014-05-16  9:10 ` [deathsimple/drm-next-3.16][PATCH V3 2/4] drm/radeon/hdmi: DCE3: clean ACR control Rafał Miłecki
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Rafał Miłecki @ 2014-05-16  9:10 UTC (permalink / raw)
  To: dri-devel, Christian König

DCE 3.1 and 3.2 should be programmed in a different way than DCE 2 and
DCE 3. The order of setting registers and sets of registers are
different.
It's still unsure how we will handle DCE 3.1 vs. DCE 3.2, since they
have few differences as well.
For now separate DCE 2 and DCE 3 path, so we can work on it without a
risk of breaking DCE 3.1+.

This has been tested for possible regressions on DCE32 HD4550 (RV710).

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
 drivers/gpu/drm/radeon/Makefile      |   2 +-
 drivers/gpu/drm/radeon/dce3_1_afmt.c | 222 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/r600_hdmi.c   | 149 ++---------------------
 drivers/gpu/drm/radeon/radeon_asic.c |   2 +-
 drivers/gpu/drm/radeon/radeon_asic.h |   7 ++
 5 files changed, 241 insertions(+), 141 deletions(-)
 create mode 100644 drivers/gpu/drm/radeon/dce3_1_afmt.c

diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index 0943353..dbcbfe8 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -72,7 +72,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
 	radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
 	rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
 	r200.o radeon_legacy_tv.o r600_cs.o r600_blit_shaders.o \
-	radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
+	radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o dce3_1_afmt.o \
 	evergreen.o evergreen_cs.o evergreen_blit_shaders.o \
 	evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \
 	atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \
diff --git a/drivers/gpu/drm/radeon/dce3_1_afmt.c b/drivers/gpu/drm/radeon/dce3_1_afmt.c
new file mode 100644
index 0000000..39cb922
--- /dev/null
+++ b/drivers/gpu/drm/radeon/dce3_1_afmt.c
@@ -0,0 +1,222 @@
+#include <linux/hdmi.h>
+#include <drm/drmP.h>
+#include "radeon.h"
+#include "radeon_asic.h"
+#include "r600d.h"
+
+static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector = NULL;
+	u32 tmp;
+	u8 *sadb;
+	int sad_count;
+
+	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+		if (connector->encoder == encoder) {
+			radeon_connector = to_radeon_connector(connector);
+			break;
+		}
+	}
+
+	if (!radeon_connector) {
+		DRM_ERROR("Couldn't find encoder's connector\n");
+		return;
+	}
+
+	sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
+	if (sad_count < 0) {
+		DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
+		return;
+	}
+
+	/* program the speaker allocation */
+	tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
+	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
+	/* set HDMI mode */
+	tmp |= HDMI_CONNECTION;
+	if (sad_count)
+		tmp |= SPEAKER_ALLOCATION(sadb[0]);
+	else
+		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
+	WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
+
+	kfree(sadb);
+}
+
+static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector = NULL;
+	struct cea_sad *sads;
+	int i, sad_count;
+
+	static const u16 eld_reg_to_type[][2] = {
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR2, HDMI_AUDIO_CODING_TYPE_MPEG1 },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR3, HDMI_AUDIO_CODING_TYPE_MP3 },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR4, HDMI_AUDIO_CODING_TYPE_MPEG2 },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR5, HDMI_AUDIO_CODING_TYPE_AAC_LC },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR6, HDMI_AUDIO_CODING_TYPE_DTS },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR7, HDMI_AUDIO_CODING_TYPE_ATRAC },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR9, HDMI_AUDIO_CODING_TYPE_EAC3 },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR10, HDMI_AUDIO_CODING_TYPE_DTS_HD },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR11, HDMI_AUDIO_CODING_TYPE_MLP },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
+	};
+
+	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+		if (connector->encoder == encoder) {
+			radeon_connector = to_radeon_connector(connector);
+			break;
+		}
+	}
+
+	if (!radeon_connector) {
+		DRM_ERROR("Couldn't find encoder's connector\n");
+		return;
+	}
+
+	sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
+	if (sad_count < 0) {
+		DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
+		return;
+	}
+	BUG_ON(!sads);
+
+	for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
+		u32 value = 0;
+		u8 stereo_freqs = 0;
+		int max_channels = -1;
+		int j;
+
+		for (j = 0; j < sad_count; j++) {
+			struct cea_sad *sad = &sads[j];
+
+			if (sad->format == eld_reg_to_type[i][1]) {
+				if (sad->channels > max_channels) {
+					value = MAX_CHANNELS(sad->channels) |
+						DESCRIPTOR_BYTE_2(sad->byte2) |
+						SUPPORTED_FREQUENCIES(sad->freq);
+					max_channels = sad->channels;
+				}
+
+				if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM)
+					stereo_freqs |= sad->freq;
+				else
+					break;
+			}
+		}
+
+		value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs);
+
+		WREG32(eld_reg_to_type[i][0], value);
+	}
+
+	kfree(sads);
+}
+
+/*
+ * update the info frames with the data from the current display mode
+ */
+void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
+{
+	struct drm_device *dev = encoder->dev;
+	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;
+	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
+	struct hdmi_avi_infoframe frame;
+	uint32_t offset;
+	ssize_t err;
+
+	if (!dig || !dig->afmt)
+		return;
+
+	/* Silent, r600_hdmi_enable will raise WARN for us */
+	if (!dig->afmt->enabled)
+		return;
+	offset = dig->afmt->offset;
+
+	/* disable audio prior to setting up hw */
+	dig->afmt->pin = r600_audio_get_pin(rdev);
+	r600_audio_enable(rdev, dig->afmt->pin, false);
+
+	r600_audio_set_dto(encoder, mode->clock);
+
+	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
+	       HDMI0_NULL_SEND); /* send null packets when required */
+
+	WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
+
+	if (ASIC_IS_DCE32(rdev)) {
+		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
+		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
+		       HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
+		WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
+		       AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */
+		       AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
+	} else {
+		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
+		       HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
+		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
+		       HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
+		       HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
+	}
+
+	if (ASIC_IS_DCE32(rdev)) {
+		dce3_2_afmt_write_speaker_allocation(encoder);
+		dce3_2_afmt_write_sad_regs(encoder);
+	}
+
+	WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
+	       HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
+	       HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
+
+	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
+	       HDMI0_NULL_SEND | /* send null packets when required */
+	       HDMI0_GC_SEND | /* send general control packets */
+	       HDMI0_GC_CONT); /* send general control packets every frame */
+
+	/* TODO: HDMI0_AUDIO_INFO_UPDATE */
+	WREG32(HDMI0_INFOFRAME_CONTROL0 + offset,
+	       HDMI0_AVI_INFO_SEND | /* enable AVI info frames */
+	       HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */
+	       HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
+	       HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */
+
+	WREG32(HDMI0_INFOFRAME_CONTROL1 + offset,
+	       HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */
+	       HDMI0_AUDIO_INFO_LINE(2)); /* anything other than 0 */
+
+	WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */
+
+	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+	if (err < 0) {
+		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
+		return;
+	}
+
+	err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
+	if (err < 0) {
+		DRM_ERROR("failed to pack AVI infoframe: %zd\n", err);
+		return;
+	}
+
+	r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer));
+	r600_hdmi_update_ACR(encoder, mode->clock);
+
+	/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
+	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);
+
+	/* enable audio after to setting up hw */
+	r600_audio_enable(rdev, dig->afmt->pin, true);
+}
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index 85a2bb2..b8b2efa 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -133,7 +133,7 @@ struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock)
 /*
  * update the N and CTS parameters for a given pixel clock rate
  */
-static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
+void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -155,8 +155,8 @@ static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
 /*
  * build a HDMI Video Info Frame
  */
-static void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
-					   void *buffer, size_t size)
+void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer,
+				    size_t size)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -231,7 +231,7 @@ int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder)
 /*
  * write the audio workaround status to the hardware
  */
-static void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
+void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -250,7 +250,7 @@ static void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
 		 value, ~HDMI0_AUDIO_TEST_EN);
 }
 
-static void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
+void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -320,121 +320,6 @@ static void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
 	}
 }
 
-static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
-{
-	struct radeon_device *rdev = encoder->dev->dev_private;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
-	u32 tmp;
-	u8 *sadb;
-	int sad_count;
-
-	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
-
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
-		return;
-	}
-
-	sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
-	if (sad_count < 0) {
-		DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
-		return;
-	}
-
-	/* program the speaker allocation */
-	tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
-	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
-	/* set HDMI mode */
-	tmp |= HDMI_CONNECTION;
-	if (sad_count)
-		tmp |= SPEAKER_ALLOCATION(sadb[0]);
-	else
-		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
-	WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
-
-	kfree(sadb);
-}
-
-static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder)
-{
-	struct radeon_device *rdev = encoder->dev->dev_private;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
-	struct cea_sad *sads;
-	int i, sad_count;
-
-	static const u16 eld_reg_to_type[][2] = {
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR2, HDMI_AUDIO_CODING_TYPE_MPEG1 },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR3, HDMI_AUDIO_CODING_TYPE_MP3 },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR4, HDMI_AUDIO_CODING_TYPE_MPEG2 },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR5, HDMI_AUDIO_CODING_TYPE_AAC_LC },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR6, HDMI_AUDIO_CODING_TYPE_DTS },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR7, HDMI_AUDIO_CODING_TYPE_ATRAC },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR9, HDMI_AUDIO_CODING_TYPE_EAC3 },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR10, HDMI_AUDIO_CODING_TYPE_DTS_HD },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR11, HDMI_AUDIO_CODING_TYPE_MLP },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
-	};
-
-	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
-
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
-		return;
-	}
-
-	sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
-	if (sad_count < 0) {
-		DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
-		return;
-	}
-	BUG_ON(!sads);
-
-	for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
-		u32 value = 0;
-		u8 stereo_freqs = 0;
-		int max_channels = -1;
-		int j;
-
-		for (j = 0; j < sad_count; j++) {
-			struct cea_sad *sad = &sads[j];
-
-			if (sad->format == eld_reg_to_type[i][1]) {
-				if (sad->channels > max_channels) {
-					value = MAX_CHANNELS(sad->channels) |
-						DESCRIPTOR_BYTE_2(sad->byte2) |
-						SUPPORTED_FREQUENCIES(sad->freq);
-					max_channels = sad->channels;
-				}
-
-				if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM)
-					stereo_freqs |= sad->freq;
-				else
-					break;
-			}
-		}
-
-		value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs);
-
-		WREG32(eld_reg_to_type[i][0], value);
-	}
-
-	kfree(sads);
-}
-
 /*
  * update the info frames with the data from the current display mode
  */
@@ -468,25 +353,11 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
 
 	WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
 
-	if (ASIC_IS_DCE32(rdev)) {
-		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
-		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
-		       HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
-		WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
-		       AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */
-		       AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
-	} else {
-		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
-		       HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
-		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
-		       HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
-		       HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
-	}
-
-	if (ASIC_IS_DCE32(rdev)) {
-		dce3_2_afmt_write_speaker_allocation(encoder);
-		dce3_2_afmt_write_sad_regs(encoder);
-	}
+	WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
+	       HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
+	       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
+	       HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
+	       HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
 
 	WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
 	       HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index 59d56dc..7bc3605 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -1214,7 +1214,7 @@ static struct radeon_asic rv770_asic = {
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.hdmi_enable = &r600_hdmi_enable,
-		.hdmi_setmode = &r600_hdmi_setmode,
+		.hdmi_setmode = &dce3_1_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &r600_copy_cpdma,
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 5646f9d..deb8496 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -391,6 +391,11 @@ void r600_rlc_stop(struct radeon_device *rdev);
 int r600_audio_init(struct radeon_device *rdev);
 struct r600_audio_pin r600_audio_status(struct radeon_device *rdev);
 void r600_audio_fini(struct radeon_device *rdev);
+void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock);
+void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer,
+				    size_t size);
+void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock);
+void r600_hdmi_audio_workaround(struct drm_encoder *encoder);
 int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
 void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
 void r600_hdmi_enable(struct drm_encoder *encoder, bool enable);
@@ -463,6 +468,8 @@ int rv770_copy_dma(struct radeon_device *rdev,
 u32 rv770_get_xclk(struct radeon_device *rdev);
 int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 int rv770_get_temp(struct radeon_device *rdev);
+/* hdmi */
+void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
 /* rv7xx pm */
 int rv770_dpm_init(struct radeon_device *rdev);
 int rv770_dpm_enable(struct radeon_device *rdev);
-- 
1.8.4.5

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [deathsimple/drm-next-3.16][PATCH V3 2/4] drm/radeon/hdmi: DCE3: clean ACR control
  2014-05-16  9:10 [deathsimple/drm-next-3.16][PATCH V3 1/4] drm/radeon/hdmi: use separated file for DCE 3.1/3.2 code Rafał Miłecki
@ 2014-05-16  9:10 ` Rafał Miłecki
  2014-05-16 22:00   ` Alex Deucher
  2014-05-16  9:10 ` [deathsimple/drm-next-3.16][PATCH V3 3/4] drm/radeon/hdmi: DCE2: update setmode Rafał Miłecki
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Rafał Miłecki @ 2014-05-16  9:10 UTC (permalink / raw)
  To: dri-devel, Christian König

What initially seemed to be a typo in fglrx (using register 0x740c
instead of 0x74dc) appeared to be a correct behavior. DCE3 has ACR and
CRC registers swapped which explains why we needed
WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);

This has been tested for possible regressions on DCE3 HD3470 (RV620).

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
V2: Use defines for swapped regs, update commit message.
---
 drivers/gpu/drm/radeon/r600_hdmi.c | 8 +++++---
 drivers/gpu/drm/radeon/r600d.h     | 2 ++
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index b8b2efa..a828222e 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -332,6 +332,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
 	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
 	struct hdmi_avi_infoframe frame;
 	uint32_t offset;
+	uint32_t acr_ctl;
 	ssize_t err;
 
 	if (!dig || !dig->afmt)
@@ -351,15 +352,16 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
 	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
 	       HDMI0_NULL_SEND); /* send null packets when required */
 
-	WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
-
 	WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
 	       HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
 	       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
 	       HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
 	       HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
 
-	WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
+	/* DCE 3.0 uses register that's normally for CRC_CONTROL */
+	acr_ctl = ASIC_IS_DCE3(rdev) ? DCE3_HDMI0_ACR_PACKET_CONTROL :
+				       HDMI0_ACR_PACKET_CONTROL;
+	WREG32(acr_ctl + offset,
 	       HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
 	       HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
 
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index 37455f6..10380c5 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -1038,6 +1038,7 @@
 #       define HDMI0_AZ_FORMAT_WTRIG_ACK   (1 << 29)
 #define HDMI0_AUDIO_CRC_CONTROL      0x740c
 #       define HDMI0_AUDIO_CRC_EN    (1 << 0)
+#define DCE3_HDMI0_ACR_PACKET_CONTROL	0x740c
 #define HDMI0_VBI_PACKET_CONTROL     0x7410
 #       define HDMI0_NULL_SEND       (1 << 0)
 #       define HDMI0_GC_SEND         (1 << 4)
@@ -1166,6 +1167,7 @@
 #       define HDMI0_ACR_48          3
 #       define HDMI0_ACR_SOURCE      (1 << 8) /* 0 - hw; 1 - cts value */
 #       define HDMI0_ACR_AUTO_SEND   (1 << 12)
+#define DCE3_HDMI0_AUDIO_CRC_CONTROL	0x74dc
 #define HDMI0_RAMP_CONTROL0          0x74e0
 #       define HDMI0_RAMP_MAX_COUNT(x)   (((x) & 0xffffff) << 0)
 #define HDMI0_RAMP_CONTROL1          0x74e4
-- 
1.8.4.5

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [deathsimple/drm-next-3.16][PATCH V3 3/4] drm/radeon/hdmi: DCE2: update setmode
  2014-05-16  9:10 [deathsimple/drm-next-3.16][PATCH V3 1/4] drm/radeon/hdmi: use separated file for DCE 3.1/3.2 code Rafał Miłecki
  2014-05-16  9:10 ` [deathsimple/drm-next-3.16][PATCH V3 2/4] drm/radeon/hdmi: DCE3: clean ACR control Rafał Miłecki
@ 2014-05-16  9:10 ` Rafał Miłecki
  2014-05-16  9:10 ` [deathsimple/drm-next-3.16][PATCH V3 4/4] drm/radeon/hdmi: DCE2: simplify audio workaround Rafał Miłecki
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Rafał Miłecki @ 2014-05-16  9:10 UTC (permalink / raw)
  To: dri-devel, Christian König

Recent RE efforts revealed ops performed by fglrx during HDMI setup.
This mostly adds masks to r/w ops plus few single missing bits.

This has been tested for possible regressions on:
1) DCE2 HD2400 (RV610)
2) DCE3 HD3470 (RV620)

For a reference and details see:
https://bugzilla.kernel.org/show_bug.cgi?id=76231

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
V2: Move r600d.h changes to 0003 (from 0004) to don't break compilation
    Fix typo in commit message
    Leave comment about DCE 3.0 and ACR control
V3: Rebase
---
 drivers/gpu/drm/radeon/r600_hdmi.c | 112 +++++++++++++++++++++++++------------
 drivers/gpu/drm/radeon/r600d.h     |  15 +++++
 2 files changed, 90 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index a828222e..a90914f 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -142,14 +142,26 @@ void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 	uint32_t offset = dig->afmt->offset;
 
-	WREG32(HDMI0_ACR_32_0 + offset, HDMI0_ACR_CTS_32(acr.cts_32khz));
-	WREG32(HDMI0_ACR_32_1 + offset, acr.n_32khz);
-
-	WREG32(HDMI0_ACR_44_0 + offset, HDMI0_ACR_CTS_44(acr.cts_44_1khz));
-	WREG32(HDMI0_ACR_44_1 + offset, acr.n_44_1khz);
-
-	WREG32(HDMI0_ACR_48_0 + offset, HDMI0_ACR_CTS_48(acr.cts_48khz));
-	WREG32(HDMI0_ACR_48_1 + offset, acr.n_48khz);
+	WREG32_P(HDMI0_ACR_32_0 + offset,
+		 HDMI0_ACR_CTS_32(acr.cts_32khz),
+		 ~HDMI0_ACR_CTS_32_MASK);
+	WREG32_P(HDMI0_ACR_32_1 + offset,
+		 HDMI0_ACR_N_32(acr.n_32khz),
+		 ~HDMI0_ACR_N_32_MASK);
+
+	WREG32_P(HDMI0_ACR_44_0 + offset,
+		 HDMI0_ACR_CTS_44(acr.cts_44_1khz),
+		 ~HDMI0_ACR_CTS_44_MASK);
+	WREG32_P(HDMI0_ACR_44_1 + offset,
+		 HDMI0_ACR_N_44(acr.n_44_1khz),
+		 ~HDMI0_ACR_N_44_MASK);
+
+	WREG32_P(HDMI0_ACR_48_0 + offset,
+		 HDMI0_ACR_CTS_48(acr.cts_48khz),
+		 ~HDMI0_ACR_CTS_48_MASK);
+	WREG32_P(HDMI0_ACR_48_1 + offset,
+		 HDMI0_ACR_N_48(acr.n_48khz),
+		 ~HDMI0_ACR_N_48_MASK);
 }
 
 /*
@@ -349,39 +361,44 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
 
 	r600_audio_set_dto(encoder, mode->clock);
 
-	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
-	       HDMI0_NULL_SEND); /* send null packets when required */
-
-	WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
-	       HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
-	       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
-	       HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
-	       HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
+	WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset,
+		 HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
+		 HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
+		 HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
+		 HDMI0_60958_CS_UPDATE, /* allow 60958 channel status fields to be updated */
+		 ~(HDMI0_AUDIO_SAMPLE_SEND |
+		   HDMI0_AUDIO_DELAY_EN_MASK |
+		   HDMI0_AUDIO_PACKETS_PER_LINE_MASK |
+		   HDMI0_60958_CS_UPDATE));
 
 	/* DCE 3.0 uses register that's normally for CRC_CONTROL */
 	acr_ctl = ASIC_IS_DCE3(rdev) ? DCE3_HDMI0_ACR_PACKET_CONTROL :
 				       HDMI0_ACR_PACKET_CONTROL;
-	WREG32(acr_ctl + offset,
-	       HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
-	       HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
-
-	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
-	       HDMI0_NULL_SEND | /* send null packets when required */
-	       HDMI0_GC_SEND | /* send general control packets */
-	       HDMI0_GC_CONT); /* send general control packets every frame */
-
-	/* TODO: HDMI0_AUDIO_INFO_UPDATE */
-	WREG32(HDMI0_INFOFRAME_CONTROL0 + offset,
-	       HDMI0_AVI_INFO_SEND | /* enable AVI info frames */
-	       HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */
-	       HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
-	       HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */
-
-	WREG32(HDMI0_INFOFRAME_CONTROL1 + offset,
-	       HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */
-	       HDMI0_AUDIO_INFO_LINE(2)); /* anything other than 0 */
-
-	WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */
+	WREG32_P(acr_ctl + offset,
+		 HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
+		 HDMI0_ACR_AUTO_SEND, /* allow hw to sent ACR packets when required */
+		 ~(HDMI0_ACR_SOURCE |
+		   HDMI0_ACR_AUTO_SEND));
+
+	WREG32_OR(HDMI0_VBI_PACKET_CONTROL + offset,
+		  HDMI0_NULL_SEND | /* send null packets when required */
+		  HDMI0_GC_SEND | /* send general control packets */
+		  HDMI0_GC_CONT); /* send general control packets every frame */
+
+	WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset,
+		  HDMI0_AVI_INFO_SEND | /* enable AVI info frames */
+		  HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */
+		  HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
+		  HDMI0_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */
+
+	WREG32_P(HDMI0_INFOFRAME_CONTROL1 + offset,
+		 HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */
+		 HDMI0_AUDIO_INFO_LINE(2), /* anything other than 0 */
+		 ~(HDMI0_AVI_INFO_LINE_MASK |
+		   HDMI0_AUDIO_INFO_LINE_MASK));
+
+	WREG32_AND(HDMI0_GC + offset,
+		   ~HDMI0_GC_AVMUTE); /* unset HDMI0_GC_AVMUTE */
 
 	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
 	if (err < 0) {
@@ -396,8 +413,29 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
 	}
 
 	r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer));
+
+	/* fglrx duplicates INFOFRAME_CONTROL0 & INFOFRAME_CONTROL1 ops here */
+
+	WREG32_AND(HDMI0_GENERIC_PACKET_CONTROL + offset,
+		   ~(HDMI0_GENERIC0_SEND |
+		     HDMI0_GENERIC0_CONT |
+		     HDMI0_GENERIC0_UPDATE |
+		     HDMI0_GENERIC1_SEND |
+		     HDMI0_GENERIC1_CONT |
+		     HDMI0_GENERIC0_LINE_MASK |
+		     HDMI0_GENERIC1_LINE_MASK));
+
 	r600_hdmi_update_ACR(encoder, mode->clock);
 
+	WREG32_P(HDMI0_60958_0 + offset,
+		 HDMI0_60958_CS_CHANNEL_NUMBER_L(1),
+		 ~(HDMI0_60958_CS_CHANNEL_NUMBER_L_MASK |
+		   HDMI0_60958_CS_CLOCK_ACCURACY_MASK));
+
+	WREG32_P(HDMI0_60958_1 + offset,
+		 HDMI0_60958_CS_CHANNEL_NUMBER_R(2),
+		 ~HDMI0_60958_CS_CHANNEL_NUMBER_R_MASK);
+
 	/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
 	WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF);
 	WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF);
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index 10380c5..f94e7a9 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -1029,9 +1029,11 @@
 #define HDMI0_AUDIO_PACKET_CONTROL   0x7408
 #       define HDMI0_AUDIO_SAMPLE_SEND  (1 << 0)
 #       define HDMI0_AUDIO_DELAY_EN(x)  (((x) & 3) << 4)
+#       define HDMI0_AUDIO_DELAY_EN_MASK	(3 << 4)
 #       define HDMI0_AUDIO_SEND_MAX_PACKETS  (1 << 8)
 #       define HDMI0_AUDIO_TEST_EN         (1 << 12)
 #       define HDMI0_AUDIO_PACKETS_PER_LINE(x)  (((x) & 0x1f) << 16)
+#       define HDMI0_AUDIO_PACKETS_PER_LINE_MASK	(0x1f << 16)
 #       define HDMI0_AUDIO_CHANNEL_SWAP    (1 << 24)
 #       define HDMI0_60958_CS_UPDATE       (1 << 26)
 #       define HDMI0_AZ_FORMAT_WTRIG_MASK  (1 << 28)
@@ -1055,7 +1057,9 @@
 #       define HDMI0_MPEG_INFO_UPDATE  (1 << 10)
 #define HDMI0_INFOFRAME_CONTROL1     0x7418
 #       define HDMI0_AVI_INFO_LINE(x)  (((x) & 0x3f) << 0)
+#       define HDMI0_AVI_INFO_LINE_MASK		(0x3f << 0)
 #       define HDMI0_AUDIO_INFO_LINE(x)  (((x) & 0x3f) << 8)
+#       define HDMI0_AUDIO_INFO_LINE_MASK	(0x3f << 8)
 #       define HDMI0_MPEG_INFO_LINE(x)  (((x) & 0x3f) << 16)
 #define HDMI0_GENERIC_PACKET_CONTROL 0x741c
 #       define HDMI0_GENERIC0_SEND   (1 << 0)
@@ -1064,7 +1068,9 @@
 #       define HDMI0_GENERIC1_SEND   (1 << 4)
 #       define HDMI0_GENERIC1_CONT   (1 << 5)
 #       define HDMI0_GENERIC0_LINE(x)  (((x) & 0x3f) << 16)
+#       define HDMI0_GENERIC0_LINE_MASK		(0x3f << 16)
 #       define HDMI0_GENERIC1_LINE(x)  (((x) & 0x3f) << 24)
+#       define HDMI0_GENERIC1_LINE_MASK		(0x3f << 24)
 #define HDMI0_GC                     0x7428
 #       define HDMI0_GC_AVMUTE       (1 << 0)
 #define HDMI0_AVI_INFO0              0x7454
@@ -1120,16 +1126,22 @@
 #define HDMI0_GENERIC1_6             0x74a8
 #define HDMI0_ACR_32_0               0x74ac
 #       define HDMI0_ACR_CTS_32(x)   (((x) & 0xfffff) << 12)
+#       define HDMI0_ACR_CTS_32_MASK		(0xfffff << 12)
 #define HDMI0_ACR_32_1               0x74b0
 #       define HDMI0_ACR_N_32(x)   (((x) & 0xfffff) << 0)
+#       define HDMI0_ACR_N_32_MASK		(0xfffff << 0)
 #define HDMI0_ACR_44_0               0x74b4
 #       define HDMI0_ACR_CTS_44(x)   (((x) & 0xfffff) << 12)
+#       define HDMI0_ACR_CTS_44_MASK		(0xfffff << 12)
 #define HDMI0_ACR_44_1               0x74b8
 #       define HDMI0_ACR_N_44(x)   (((x) & 0xfffff) << 0)
+#       define HDMI0_ACR_N_44_MASK		(0xfffff << 0)
 #define HDMI0_ACR_48_0               0x74bc
 #       define HDMI0_ACR_CTS_48(x)   (((x) & 0xfffff) << 12)
+#       define HDMI0_ACR_CTS_48_MASK		(0xfffff << 12)
 #define HDMI0_ACR_48_1               0x74c0
 #       define HDMI0_ACR_N_48(x)   (((x) & 0xfffff) << 0)
+#       define HDMI0_ACR_N_48_MASK		(0xfffff << 0)
 #define HDMI0_ACR_STATUS_0           0x74c4
 #define HDMI0_ACR_STATUS_1           0x74c8
 #define HDMI0_AUDIO_INFO0            0x74cc
@@ -1149,14 +1161,17 @@
 #       define HDMI0_60958_CS_CATEGORY_CODE(x)      (((x) & 0xff) << 8)
 #       define HDMI0_60958_CS_SOURCE_NUMBER(x)      (((x) & 0xf) << 16)
 #       define HDMI0_60958_CS_CHANNEL_NUMBER_L(x)   (((x) & 0xf) << 20)
+#       define HDMI0_60958_CS_CHANNEL_NUMBER_L_MASK	(0xf << 20)
 #       define HDMI0_60958_CS_SAMPLING_FREQUENCY(x) (((x) & 0xf) << 24)
 #       define HDMI0_60958_CS_CLOCK_ACCURACY(x)     (((x) & 3) << 28)
+#       define HDMI0_60958_CS_CLOCK_ACCURACY_MASK	(3 << 28)
 #define HDMI0_60958_1                0x74d8
 #       define HDMI0_60958_CS_WORD_LENGTH(x)        (((x) & 0xf) << 0)
 #       define HDMI0_60958_CS_ORIGINAL_SAMPLING_FREQUENCY(x)   (((x) & 0xf) << 4)
 #       define HDMI0_60958_CS_VALID_L(x)   (((x) & 1) << 16)
 #       define HDMI0_60958_CS_VALID_R(x)   (((x) & 1) << 18)
 #       define HDMI0_60958_CS_CHANNEL_NUMBER_R(x)   (((x) & 0xf) << 20)
+#       define HDMI0_60958_CS_CHANNEL_NUMBER_R_MASK	(0xf << 20)
 #define HDMI0_ACR_PACKET_CONTROL     0x74dc
 #       define HDMI0_ACR_SEND        (1 << 0)
 #       define HDMI0_ACR_CONT        (1 << 1)
-- 
1.8.4.5

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [deathsimple/drm-next-3.16][PATCH V3 4/4] drm/radeon/hdmi: DCE2: simplify audio workaround
  2014-05-16  9:10 [deathsimple/drm-next-3.16][PATCH V3 1/4] drm/radeon/hdmi: use separated file for DCE 3.1/3.2 code Rafał Miłecki
  2014-05-16  9:10 ` [deathsimple/drm-next-3.16][PATCH V3 2/4] drm/radeon/hdmi: DCE3: clean ACR control Rafał Miłecki
  2014-05-16  9:10 ` [deathsimple/drm-next-3.16][PATCH V3 3/4] drm/radeon/hdmi: DCE2: update setmode Rafał Miłecki
@ 2014-05-16  9:10 ` Rafał Miłecki
  2014-05-16  9:22 ` [deathsimple/drm-next-3.16][PATCH V3 1/4] drm/radeon/hdmi: use separated file for DCE 3.1/3.2 code Christian König
  2014-05-16  9:36 ` [deathsimple/drm-next-3.16][PATCH V4 " Rafał Miłecki
  4 siblings, 0 replies; 12+ messages in thread
From: Rafał Miłecki @ 2014-05-16  9:10 UTC (permalink / raw)
  To: dri-devel, Christian König

Thanks to advanced RE of fglrx we finally know what exactly needs to be
handled of AFMT change.

This has been tested for possible regressions on:
1) DCE2 HD2400 (RV610)
2) DCE3 HD3470 (RV620)

For a reference and details see:
https://bugzilla.kernel.org/show_bug.cgi?id=76231

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
V2: Move r600d.h changes to 0003 (from 0004) to don't break compilation
    Fix typo in commit message
---
 drivers/gpu/drm/radeon/r600_hdmi.c | 82 ++++++++++----------------------------
 1 file changed, 22 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index a90914f..26ef8ce 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -442,14 +442,16 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
 	WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001);
 	WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001);
 
-	r600_hdmi_audio_workaround(encoder);
-
 	/* enable audio after to setting up hw */
 	r600_audio_enable(rdev, dig->afmt->pin, true);
 }
 
-/*
- * update settings with current parameters from audio engine
+/**
+ * r600_hdmi_update_audio_settings - Update audio infoframe
+ *
+ * @encoder: drm encoder
+ *
+ * Gets info about current audio stream and updates audio infoframe.
  */
 void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
 {
@@ -461,7 +463,7 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
 	uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE];
 	struct hdmi_audio_infoframe frame;
 	uint32_t offset;
-	uint32_t iec;
+	uint32_t value;
 	ssize_t err;
 
 	if (!dig->afmt || !dig->afmt->enabled)
@@ -474,60 +476,6 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
 	DRM_DEBUG("0x%02X IEC60958 status bits and 0x%02X category code\n",
 		  (int)audio.status_bits, (int)audio.category_code);
 
-	iec = 0;
-	if (audio.status_bits & AUDIO_STATUS_PROFESSIONAL)
-		iec |= 1 << 0;
-	if (audio.status_bits & AUDIO_STATUS_NONAUDIO)
-		iec |= 1 << 1;
-	if (audio.status_bits & AUDIO_STATUS_COPYRIGHT)
-		iec |= 1 << 2;
-	if (audio.status_bits & AUDIO_STATUS_EMPHASIS)
-		iec |= 1 << 3;
-
-	iec |= HDMI0_60958_CS_CATEGORY_CODE(audio.category_code);
-
-	switch (audio.rate) {
-	case 32000:
-		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x3);
-		break;
-	case 44100:
-		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x0);
-		break;
-	case 48000:
-		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x2);
-		break;
-	case 88200:
-		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x8);
-		break;
-	case 96000:
-		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xa);
-		break;
-	case 176400:
-		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xc);
-		break;
-	case 192000:
-		iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xe);
-		break;
-	}
-
-	WREG32(HDMI0_60958_0 + offset, iec);
-
-	iec = 0;
-	switch (audio.bits_per_sample) {
-	case 16:
-		iec |= HDMI0_60958_CS_WORD_LENGTH(0x2);
-		break;
-	case 20:
-		iec |= HDMI0_60958_CS_WORD_LENGTH(0x3);
-		break;
-	case 24:
-		iec |= HDMI0_60958_CS_WORD_LENGTH(0xb);
-		break;
-	}
-	if (audio.status_bits & AUDIO_STATUS_V)
-		iec |= 0x5 << 16;
-	WREG32_P(HDMI0_60958_1 + offset, iec, ~0x5000f);
-
 	err = hdmi_audio_infoframe_init(&frame);
 	if (err < 0) {
 		DRM_ERROR("failed to setup audio infoframe\n");
@@ -542,8 +490,22 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
 		return;
 	}
 
+	value = RREG32(HDMI0_AUDIO_PACKET_CONTROL + offset);
+	if (value & HDMI0_AUDIO_TEST_EN)
+		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
+		       value & ~HDMI0_AUDIO_TEST_EN);
+
+	WREG32_OR(HDMI0_CONTROL + offset,
+		  HDMI0_ERROR_ACK);
+
+	WREG32_AND(HDMI0_INFOFRAME_CONTROL0 + offset,
+		   ~HDMI0_AUDIO_INFO_SOURCE);
+
 	r600_hdmi_update_audio_infoframe(encoder, buffer, sizeof(buffer));
-	r600_hdmi_audio_workaround(encoder);
+
+	WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset,
+		  HDMI0_AUDIO_INFO_CONT |
+		  HDMI0_AUDIO_INFO_UPDATE);
 }
 
 /*
-- 
1.8.4.5

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [deathsimple/drm-next-3.16][PATCH V3 1/4] drm/radeon/hdmi: use separated file for DCE 3.1/3.2 code
  2014-05-16  9:10 [deathsimple/drm-next-3.16][PATCH V3 1/4] drm/radeon/hdmi: use separated file for DCE 3.1/3.2 code Rafał Miłecki
                   ` (2 preceding siblings ...)
  2014-05-16  9:10 ` [deathsimple/drm-next-3.16][PATCH V3 4/4] drm/radeon/hdmi: DCE2: simplify audio workaround Rafał Miłecki
@ 2014-05-16  9:22 ` Christian König
  2014-05-16  9:36 ` [deathsimple/drm-next-3.16][PATCH V4 " Rafał Miłecki
  4 siblings, 0 replies; 12+ messages in thread
From: Christian König @ 2014-05-16  9:22 UTC (permalink / raw)
  To: Rafał Miłecki, dri-devel

> +++ b/drivers/gpu/drm/radeon/dce3_1_afmt.c
> @@ -0,0 +1,222 @@
> +#include <linux/hdmi.h>
> +#include <drm/drmP.h>
Adding the copyright header to new files would be nice.

Apart from that the series looks good to me.

Christian.

Am 16.05.2014 11:10, schrieb Rafał Miłecki:
> DCE 3.1 and 3.2 should be programmed in a different way than DCE 2 and
> DCE 3. The order of setting registers and sets of registers are
> different.
> It's still unsure how we will handle DCE 3.1 vs. DCE 3.2, since they
> have few differences as well.
> For now separate DCE 2 and DCE 3 path, so we can work on it without a
> risk of breaking DCE 3.1+.
>
> This has been tested for possible regressions on DCE32 HD4550 (RV710).
>
> Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
> ---
>   drivers/gpu/drm/radeon/Makefile      |   2 +-
>   drivers/gpu/drm/radeon/dce3_1_afmt.c | 222 +++++++++++++++++++++++++++++++++++
>   drivers/gpu/drm/radeon/r600_hdmi.c   | 149 ++---------------------
>   drivers/gpu/drm/radeon/radeon_asic.c |   2 +-
>   drivers/gpu/drm/radeon/radeon_asic.h |   7 ++
>   5 files changed, 241 insertions(+), 141 deletions(-)
>   create mode 100644 drivers/gpu/drm/radeon/dce3_1_afmt.c
>
> diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
> index 0943353..dbcbfe8 100644
> --- a/drivers/gpu/drm/radeon/Makefile
> +++ b/drivers/gpu/drm/radeon/Makefile
> @@ -72,7 +72,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
>   	radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
>   	rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
>   	r200.o radeon_legacy_tv.o r600_cs.o r600_blit_shaders.o \
> -	radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
> +	radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o dce3_1_afmt.o \
>   	evergreen.o evergreen_cs.o evergreen_blit_shaders.o \
>   	evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \
>   	atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \
> diff --git a/drivers/gpu/drm/radeon/dce3_1_afmt.c b/drivers/gpu/drm/radeon/dce3_1_afmt.c
> new file mode 100644
> index 0000000..39cb922
> --- /dev/null
> +++ b/drivers/gpu/drm/radeon/dce3_1_afmt.c
> @@ -0,0 +1,222 @@
> +#include <linux/hdmi.h>
> +#include <drm/drmP.h>
> +#include "radeon.h"
> +#include "radeon_asic.h"
> +#include "r600d.h"
> +
> +static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
> +{
> +	struct radeon_device *rdev = encoder->dev->dev_private;
> +	struct drm_connector *connector;
> +	struct radeon_connector *radeon_connector = NULL;
> +	u32 tmp;
> +	u8 *sadb;
> +	int sad_count;
> +
> +	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
> +		if (connector->encoder == encoder) {
> +			radeon_connector = to_radeon_connector(connector);
> +			break;
> +		}
> +	}
> +
> +	if (!radeon_connector) {
> +		DRM_ERROR("Couldn't find encoder's connector\n");
> +		return;
> +	}
> +
> +	sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
> +	if (sad_count < 0) {
> +		DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
> +		return;
> +	}
> +
> +	/* program the speaker allocation */
> +	tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
> +	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
> +	/* set HDMI mode */
> +	tmp |= HDMI_CONNECTION;
> +	if (sad_count)
> +		tmp |= SPEAKER_ALLOCATION(sadb[0]);
> +	else
> +		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
> +	WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
> +
> +	kfree(sadb);
> +}
> +
> +static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder)
> +{
> +	struct radeon_device *rdev = encoder->dev->dev_private;
> +	struct drm_connector *connector;
> +	struct radeon_connector *radeon_connector = NULL;
> +	struct cea_sad *sads;
> +	int i, sad_count;
> +
> +	static const u16 eld_reg_to_type[][2] = {
> +		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
> +		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
> +		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR2, HDMI_AUDIO_CODING_TYPE_MPEG1 },
> +		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR3, HDMI_AUDIO_CODING_TYPE_MP3 },
> +		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR4, HDMI_AUDIO_CODING_TYPE_MPEG2 },
> +		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR5, HDMI_AUDIO_CODING_TYPE_AAC_LC },
> +		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR6, HDMI_AUDIO_CODING_TYPE_DTS },
> +		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR7, HDMI_AUDIO_CODING_TYPE_ATRAC },
> +		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR9, HDMI_AUDIO_CODING_TYPE_EAC3 },
> +		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR10, HDMI_AUDIO_CODING_TYPE_DTS_HD },
> +		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR11, HDMI_AUDIO_CODING_TYPE_MLP },
> +		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
> +	};
> +
> +	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
> +		if (connector->encoder == encoder) {
> +			radeon_connector = to_radeon_connector(connector);
> +			break;
> +		}
> +	}
> +
> +	if (!radeon_connector) {
> +		DRM_ERROR("Couldn't find encoder's connector\n");
> +		return;
> +	}
> +
> +	sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
> +	if (sad_count < 0) {
> +		DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
> +		return;
> +	}
> +	BUG_ON(!sads);
> +
> +	for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
> +		u32 value = 0;
> +		u8 stereo_freqs = 0;
> +		int max_channels = -1;
> +		int j;
> +
> +		for (j = 0; j < sad_count; j++) {
> +			struct cea_sad *sad = &sads[j];
> +
> +			if (sad->format == eld_reg_to_type[i][1]) {
> +				if (sad->channels > max_channels) {
> +					value = MAX_CHANNELS(sad->channels) |
> +						DESCRIPTOR_BYTE_2(sad->byte2) |
> +						SUPPORTED_FREQUENCIES(sad->freq);
> +					max_channels = sad->channels;
> +				}
> +
> +				if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM)
> +					stereo_freqs |= sad->freq;
> +				else
> +					break;
> +			}
> +		}
> +
> +		value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs);
> +
> +		WREG32(eld_reg_to_type[i][0], value);
> +	}
> +
> +	kfree(sads);
> +}
> +
> +/*
> + * update the info frames with the data from the current display mode
> + */
> +void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
> +{
> +	struct drm_device *dev = encoder->dev;
> +	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;
> +	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
> +	struct hdmi_avi_infoframe frame;
> +	uint32_t offset;
> +	ssize_t err;
> +
> +	if (!dig || !dig->afmt)
> +		return;
> +
> +	/* Silent, r600_hdmi_enable will raise WARN for us */
> +	if (!dig->afmt->enabled)
> +		return;
> +	offset = dig->afmt->offset;
> +
> +	/* disable audio prior to setting up hw */
> +	dig->afmt->pin = r600_audio_get_pin(rdev);
> +	r600_audio_enable(rdev, dig->afmt->pin, false);
> +
> +	r600_audio_set_dto(encoder, mode->clock);
> +
> +	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
> +	       HDMI0_NULL_SEND); /* send null packets when required */
> +
> +	WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
> +
> +	if (ASIC_IS_DCE32(rdev)) {
> +		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
> +		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
> +		       HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
> +		WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
> +		       AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */
> +		       AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
> +	} else {
> +		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
> +		       HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
> +		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
> +		       HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
> +		       HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
> +	}
> +
> +	if (ASIC_IS_DCE32(rdev)) {
> +		dce3_2_afmt_write_speaker_allocation(encoder);
> +		dce3_2_afmt_write_sad_regs(encoder);
> +	}
> +
> +	WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
> +	       HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
> +	       HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
> +
> +	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
> +	       HDMI0_NULL_SEND | /* send null packets when required */
> +	       HDMI0_GC_SEND | /* send general control packets */
> +	       HDMI0_GC_CONT); /* send general control packets every frame */
> +
> +	/* TODO: HDMI0_AUDIO_INFO_UPDATE */
> +	WREG32(HDMI0_INFOFRAME_CONTROL0 + offset,
> +	       HDMI0_AVI_INFO_SEND | /* enable AVI info frames */
> +	       HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */
> +	       HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
> +	       HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */
> +
> +	WREG32(HDMI0_INFOFRAME_CONTROL1 + offset,
> +	       HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */
> +	       HDMI0_AUDIO_INFO_LINE(2)); /* anything other than 0 */
> +
> +	WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */
> +
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	if (err < 0) {
> +		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
> +		return;
> +	}
> +
> +	err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
> +	if (err < 0) {
> +		DRM_ERROR("failed to pack AVI infoframe: %zd\n", err);
> +		return;
> +	}
> +
> +	r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer));
> +	r600_hdmi_update_ACR(encoder, mode->clock);
> +
> +	/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
> +	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);
> +
> +	/* enable audio after to setting up hw */
> +	r600_audio_enable(rdev, dig->afmt->pin, true);
> +}
> diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
> index 85a2bb2..b8b2efa 100644
> --- a/drivers/gpu/drm/radeon/r600_hdmi.c
> +++ b/drivers/gpu/drm/radeon/r600_hdmi.c
> @@ -133,7 +133,7 @@ struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock)
>   /*
>    * update the N and CTS parameters for a given pixel clock rate
>    */
> -static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
> +void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
>   {
>   	struct drm_device *dev = encoder->dev;
>   	struct radeon_device *rdev = dev->dev_private;
> @@ -155,8 +155,8 @@ static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
>   /*
>    * build a HDMI Video Info Frame
>    */
> -static void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
> -					   void *buffer, size_t size)
> +void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer,
> +				    size_t size)
>   {
>   	struct drm_device *dev = encoder->dev;
>   	struct radeon_device *rdev = dev->dev_private;
> @@ -231,7 +231,7 @@ int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder)
>   /*
>    * write the audio workaround status to the hardware
>    */
> -static void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
> +void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
>   {
>   	struct drm_device *dev = encoder->dev;
>   	struct radeon_device *rdev = dev->dev_private;
> @@ -250,7 +250,7 @@ static void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
>   		 value, ~HDMI0_AUDIO_TEST_EN);
>   }
>   
> -static void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
> +void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
>   {
>   	struct drm_device *dev = encoder->dev;
>   	struct radeon_device *rdev = dev->dev_private;
> @@ -320,121 +320,6 @@ static void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
>   	}
>   }
>   
> -static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
> -{
> -	struct radeon_device *rdev = encoder->dev->dev_private;
> -	struct drm_connector *connector;
> -	struct radeon_connector *radeon_connector = NULL;
> -	u32 tmp;
> -	u8 *sadb;
> -	int sad_count;
> -
> -	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
> -		if (connector->encoder == encoder) {
> -			radeon_connector = to_radeon_connector(connector);
> -			break;
> -		}
> -	}
> -
> -	if (!radeon_connector) {
> -		DRM_ERROR("Couldn't find encoder's connector\n");
> -		return;
> -	}
> -
> -	sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
> -	if (sad_count < 0) {
> -		DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
> -		return;
> -	}
> -
> -	/* program the speaker allocation */
> -	tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
> -	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
> -	/* set HDMI mode */
> -	tmp |= HDMI_CONNECTION;
> -	if (sad_count)
> -		tmp |= SPEAKER_ALLOCATION(sadb[0]);
> -	else
> -		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
> -	WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
> -
> -	kfree(sadb);
> -}
> -
> -static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder)
> -{
> -	struct radeon_device *rdev = encoder->dev->dev_private;
> -	struct drm_connector *connector;
> -	struct radeon_connector *radeon_connector = NULL;
> -	struct cea_sad *sads;
> -	int i, sad_count;
> -
> -	static const u16 eld_reg_to_type[][2] = {
> -		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
> -		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
> -		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR2, HDMI_AUDIO_CODING_TYPE_MPEG1 },
> -		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR3, HDMI_AUDIO_CODING_TYPE_MP3 },
> -		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR4, HDMI_AUDIO_CODING_TYPE_MPEG2 },
> -		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR5, HDMI_AUDIO_CODING_TYPE_AAC_LC },
> -		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR6, HDMI_AUDIO_CODING_TYPE_DTS },
> -		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR7, HDMI_AUDIO_CODING_TYPE_ATRAC },
> -		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR9, HDMI_AUDIO_CODING_TYPE_EAC3 },
> -		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR10, HDMI_AUDIO_CODING_TYPE_DTS_HD },
> -		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR11, HDMI_AUDIO_CODING_TYPE_MLP },
> -		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
> -	};
> -
> -	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
> -		if (connector->encoder == encoder) {
> -			radeon_connector = to_radeon_connector(connector);
> -			break;
> -		}
> -	}
> -
> -	if (!radeon_connector) {
> -		DRM_ERROR("Couldn't find encoder's connector\n");
> -		return;
> -	}
> -
> -	sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
> -	if (sad_count < 0) {
> -		DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
> -		return;
> -	}
> -	BUG_ON(!sads);
> -
> -	for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
> -		u32 value = 0;
> -		u8 stereo_freqs = 0;
> -		int max_channels = -1;
> -		int j;
> -
> -		for (j = 0; j < sad_count; j++) {
> -			struct cea_sad *sad = &sads[j];
> -
> -			if (sad->format == eld_reg_to_type[i][1]) {
> -				if (sad->channels > max_channels) {
> -					value = MAX_CHANNELS(sad->channels) |
> -						DESCRIPTOR_BYTE_2(sad->byte2) |
> -						SUPPORTED_FREQUENCIES(sad->freq);
> -					max_channels = sad->channels;
> -				}
> -
> -				if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM)
> -					stereo_freqs |= sad->freq;
> -				else
> -					break;
> -			}
> -		}
> -
> -		value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs);
> -
> -		WREG32(eld_reg_to_type[i][0], value);
> -	}
> -
> -	kfree(sads);
> -}
> -
>   /*
>    * update the info frames with the data from the current display mode
>    */
> @@ -468,25 +353,11 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
>   
>   	WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
>   
> -	if (ASIC_IS_DCE32(rdev)) {
> -		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
> -		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
> -		       HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
> -		WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
> -		       AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */
> -		       AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
> -	} else {
> -		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
> -		       HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
> -		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
> -		       HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
> -		       HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
> -	}
> -
> -	if (ASIC_IS_DCE32(rdev)) {
> -		dce3_2_afmt_write_speaker_allocation(encoder);
> -		dce3_2_afmt_write_sad_regs(encoder);
> -	}
> +	WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
> +	       HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
> +	       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
> +	       HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
> +	       HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
>   
>   	WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
>   	       HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
> diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
> index 59d56dc..7bc3605 100644
> --- a/drivers/gpu/drm/radeon/radeon_asic.c
> +++ b/drivers/gpu/drm/radeon/radeon_asic.c
> @@ -1214,7 +1214,7 @@ static struct radeon_asic rv770_asic = {
>   		.set_backlight_level = &atombios_set_backlight_level,
>   		.get_backlight_level = &atombios_get_backlight_level,
>   		.hdmi_enable = &r600_hdmi_enable,
> -		.hdmi_setmode = &r600_hdmi_setmode,
> +		.hdmi_setmode = &dce3_1_hdmi_setmode,
>   	},
>   	.copy = {
>   		.blit = &r600_copy_cpdma,
> diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
> index 5646f9d..deb8496 100644
> --- a/drivers/gpu/drm/radeon/radeon_asic.h
> +++ b/drivers/gpu/drm/radeon/radeon_asic.h
> @@ -391,6 +391,11 @@ void r600_rlc_stop(struct radeon_device *rdev);
>   int r600_audio_init(struct radeon_device *rdev);
>   struct r600_audio_pin r600_audio_status(struct radeon_device *rdev);
>   void r600_audio_fini(struct radeon_device *rdev);
> +void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock);
> +void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer,
> +				    size_t size);
> +void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock);
> +void r600_hdmi_audio_workaround(struct drm_encoder *encoder);
>   int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
>   void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
>   void r600_hdmi_enable(struct drm_encoder *encoder, bool enable);
> @@ -463,6 +468,8 @@ int rv770_copy_dma(struct radeon_device *rdev,
>   u32 rv770_get_xclk(struct radeon_device *rdev);
>   int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
>   int rv770_get_temp(struct radeon_device *rdev);
> +/* hdmi */
> +void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
>   /* rv7xx pm */
>   int rv770_dpm_init(struct radeon_device *rdev);
>   int rv770_dpm_enable(struct radeon_device *rdev);

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [deathsimple/drm-next-3.16][PATCH V4 1/4] drm/radeon/hdmi: use separated file for DCE 3.1/3.2 code
  2014-05-16  9:10 [deathsimple/drm-next-3.16][PATCH V3 1/4] drm/radeon/hdmi: use separated file for DCE 3.1/3.2 code Rafał Miłecki
                   ` (3 preceding siblings ...)
  2014-05-16  9:22 ` [deathsimple/drm-next-3.16][PATCH V3 1/4] drm/radeon/hdmi: use separated file for DCE 3.1/3.2 code Christian König
@ 2014-05-16  9:36 ` Rafał Miłecki
  2014-05-19 15:27   ` Alex Deucher
  4 siblings, 1 reply; 12+ messages in thread
From: Rafał Miłecki @ 2014-05-16  9:36 UTC (permalink / raw)
  To: dri-devel, Christian König

DCE 3.1 and 3.2 should be programmed in a different way than DCE 2 and
DCE 3. The order of setting registers and sets of registers are
different.
It's still unsure how we will handle DCE 3.1 vs. DCE 3.2, since they
have few differences as well.
For now separate DCE 2 and DCE 3 path, so we can work on it without a
risk of breaking DCE 3.1+.

This has been tested for possible regressions on DCE32 HD4550 (RV710).

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
V4: Add Copyright header. Alex is an author of
    dce3_2_afmt_write_speaker_allocation
    dce3_2_afmt_write_sad_regs
    and I'm pretty much an author of
    dce3_1_hdmi_setmode
---
 drivers/gpu/drm/radeon/Makefile      |   2 +-
 drivers/gpu/drm/radeon/dce3_1_afmt.c | 244 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/r600_hdmi.c   | 149 ++-------------------
 drivers/gpu/drm/radeon/radeon_asic.c |   2 +-
 drivers/gpu/drm/radeon/radeon_asic.h |   7 +
 5 files changed, 263 insertions(+), 141 deletions(-)
 create mode 100644 drivers/gpu/drm/radeon/dce3_1_afmt.c

diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index 0943353..dbcbfe8 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -72,7 +72,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
 	radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
 	rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
 	r200.o radeon_legacy_tv.o r600_cs.o r600_blit_shaders.o \
-	radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
+	radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o dce3_1_afmt.o \
 	evergreen.o evergreen_cs.o evergreen_blit_shaders.o \
 	evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \
 	atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \
diff --git a/drivers/gpu/drm/radeon/dce3_1_afmt.c b/drivers/gpu/drm/radeon/dce3_1_afmt.c
new file mode 100644
index 0000000..51800e3
--- /dev/null
+++ b/drivers/gpu/drm/radeon/dce3_1_afmt.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * Copyright 2014 Rafał Miłecki
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <linux/hdmi.h>
+#include <drm/drmP.h>
+#include "radeon.h"
+#include "radeon_asic.h"
+#include "r600d.h"
+
+static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector = NULL;
+	u32 tmp;
+	u8 *sadb;
+	int sad_count;
+
+	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+		if (connector->encoder == encoder) {
+			radeon_connector = to_radeon_connector(connector);
+			break;
+		}
+	}
+
+	if (!radeon_connector) {
+		DRM_ERROR("Couldn't find encoder's connector\n");
+		return;
+	}
+
+	sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
+	if (sad_count < 0) {
+		DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
+		return;
+	}
+
+	/* program the speaker allocation */
+	tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
+	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
+	/* set HDMI mode */
+	tmp |= HDMI_CONNECTION;
+	if (sad_count)
+		tmp |= SPEAKER_ALLOCATION(sadb[0]);
+	else
+		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
+	WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
+
+	kfree(sadb);
+}
+
+static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector = NULL;
+	struct cea_sad *sads;
+	int i, sad_count;
+
+	static const u16 eld_reg_to_type[][2] = {
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR2, HDMI_AUDIO_CODING_TYPE_MPEG1 },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR3, HDMI_AUDIO_CODING_TYPE_MP3 },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR4, HDMI_AUDIO_CODING_TYPE_MPEG2 },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR5, HDMI_AUDIO_CODING_TYPE_AAC_LC },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR6, HDMI_AUDIO_CODING_TYPE_DTS },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR7, HDMI_AUDIO_CODING_TYPE_ATRAC },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR9, HDMI_AUDIO_CODING_TYPE_EAC3 },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR10, HDMI_AUDIO_CODING_TYPE_DTS_HD },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR11, HDMI_AUDIO_CODING_TYPE_MLP },
+		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
+	};
+
+	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+		if (connector->encoder == encoder) {
+			radeon_connector = to_radeon_connector(connector);
+			break;
+		}
+	}
+
+	if (!radeon_connector) {
+		DRM_ERROR("Couldn't find encoder's connector\n");
+		return;
+	}
+
+	sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
+	if (sad_count < 0) {
+		DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
+		return;
+	}
+	BUG_ON(!sads);
+
+	for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
+		u32 value = 0;
+		u8 stereo_freqs = 0;
+		int max_channels = -1;
+		int j;
+
+		for (j = 0; j < sad_count; j++) {
+			struct cea_sad *sad = &sads[j];
+
+			if (sad->format == eld_reg_to_type[i][1]) {
+				if (sad->channels > max_channels) {
+					value = MAX_CHANNELS(sad->channels) |
+						DESCRIPTOR_BYTE_2(sad->byte2) |
+						SUPPORTED_FREQUENCIES(sad->freq);
+					max_channels = sad->channels;
+				}
+
+				if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM)
+					stereo_freqs |= sad->freq;
+				else
+					break;
+			}
+		}
+
+		value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs);
+
+		WREG32(eld_reg_to_type[i][0], value);
+	}
+
+	kfree(sads);
+}
+
+/*
+ * update the info frames with the data from the current display mode
+ */
+void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
+{
+	struct drm_device *dev = encoder->dev;
+	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;
+	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
+	struct hdmi_avi_infoframe frame;
+	uint32_t offset;
+	ssize_t err;
+
+	if (!dig || !dig->afmt)
+		return;
+
+	/* Silent, r600_hdmi_enable will raise WARN for us */
+	if (!dig->afmt->enabled)
+		return;
+	offset = dig->afmt->offset;
+
+	/* disable audio prior to setting up hw */
+	dig->afmt->pin = r600_audio_get_pin(rdev);
+	r600_audio_enable(rdev, dig->afmt->pin, false);
+
+	r600_audio_set_dto(encoder, mode->clock);
+
+	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
+	       HDMI0_NULL_SEND); /* send null packets when required */
+
+	WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
+
+	if (ASIC_IS_DCE32(rdev)) {
+		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
+		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
+		       HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
+		WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
+		       AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */
+		       AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
+	} else {
+		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
+		       HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
+		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
+		       HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
+		       HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
+	}
+
+	if (ASIC_IS_DCE32(rdev)) {
+		dce3_2_afmt_write_speaker_allocation(encoder);
+		dce3_2_afmt_write_sad_regs(encoder);
+	}
+
+	WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
+	       HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
+	       HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
+
+	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
+	       HDMI0_NULL_SEND | /* send null packets when required */
+	       HDMI0_GC_SEND | /* send general control packets */
+	       HDMI0_GC_CONT); /* send general control packets every frame */
+
+	/* TODO: HDMI0_AUDIO_INFO_UPDATE */
+	WREG32(HDMI0_INFOFRAME_CONTROL0 + offset,
+	       HDMI0_AVI_INFO_SEND | /* enable AVI info frames */
+	       HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */
+	       HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
+	       HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */
+
+	WREG32(HDMI0_INFOFRAME_CONTROL1 + offset,
+	       HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */
+	       HDMI0_AUDIO_INFO_LINE(2)); /* anything other than 0 */
+
+	WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */
+
+	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+	if (err < 0) {
+		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
+		return;
+	}
+
+	err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
+	if (err < 0) {
+		DRM_ERROR("failed to pack AVI infoframe: %zd\n", err);
+		return;
+	}
+
+	r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer));
+	r600_hdmi_update_ACR(encoder, mode->clock);
+
+	/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
+	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);
+
+	/* enable audio after to setting up hw */
+	r600_audio_enable(rdev, dig->afmt->pin, true);
+}
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index 85a2bb2..b8b2efa 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -133,7 +133,7 @@ struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock)
 /*
  * update the N and CTS parameters for a given pixel clock rate
  */
-static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
+void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -155,8 +155,8 @@ static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
 /*
  * build a HDMI Video Info Frame
  */
-static void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
-					   void *buffer, size_t size)
+void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer,
+				    size_t size)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -231,7 +231,7 @@ int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder)
 /*
  * write the audio workaround status to the hardware
  */
-static void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
+void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -250,7 +250,7 @@ static void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
 		 value, ~HDMI0_AUDIO_TEST_EN);
 }
 
-static void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
+void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -320,121 +320,6 @@ static void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
 	}
 }
 
-static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
-{
-	struct radeon_device *rdev = encoder->dev->dev_private;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
-	u32 tmp;
-	u8 *sadb;
-	int sad_count;
-
-	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
-
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
-		return;
-	}
-
-	sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
-	if (sad_count < 0) {
-		DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
-		return;
-	}
-
-	/* program the speaker allocation */
-	tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
-	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
-	/* set HDMI mode */
-	tmp |= HDMI_CONNECTION;
-	if (sad_count)
-		tmp |= SPEAKER_ALLOCATION(sadb[0]);
-	else
-		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
-	WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
-
-	kfree(sadb);
-}
-
-static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder)
-{
-	struct radeon_device *rdev = encoder->dev->dev_private;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
-	struct cea_sad *sads;
-	int i, sad_count;
-
-	static const u16 eld_reg_to_type[][2] = {
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR2, HDMI_AUDIO_CODING_TYPE_MPEG1 },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR3, HDMI_AUDIO_CODING_TYPE_MP3 },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR4, HDMI_AUDIO_CODING_TYPE_MPEG2 },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR5, HDMI_AUDIO_CODING_TYPE_AAC_LC },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR6, HDMI_AUDIO_CODING_TYPE_DTS },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR7, HDMI_AUDIO_CODING_TYPE_ATRAC },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR9, HDMI_AUDIO_CODING_TYPE_EAC3 },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR10, HDMI_AUDIO_CODING_TYPE_DTS_HD },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR11, HDMI_AUDIO_CODING_TYPE_MLP },
-		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
-	};
-
-	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
-
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
-		return;
-	}
-
-	sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
-	if (sad_count < 0) {
-		DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
-		return;
-	}
-	BUG_ON(!sads);
-
-	for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
-		u32 value = 0;
-		u8 stereo_freqs = 0;
-		int max_channels = -1;
-		int j;
-
-		for (j = 0; j < sad_count; j++) {
-			struct cea_sad *sad = &sads[j];
-
-			if (sad->format == eld_reg_to_type[i][1]) {
-				if (sad->channels > max_channels) {
-					value = MAX_CHANNELS(sad->channels) |
-						DESCRIPTOR_BYTE_2(sad->byte2) |
-						SUPPORTED_FREQUENCIES(sad->freq);
-					max_channels = sad->channels;
-				}
-
-				if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM)
-					stereo_freqs |= sad->freq;
-				else
-					break;
-			}
-		}
-
-		value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs);
-
-		WREG32(eld_reg_to_type[i][0], value);
-	}
-
-	kfree(sads);
-}
-
 /*
  * update the info frames with the data from the current display mode
  */
@@ -468,25 +353,11 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
 
 	WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
 
-	if (ASIC_IS_DCE32(rdev)) {
-		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
-		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
-		       HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
-		WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
-		       AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */
-		       AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
-	} else {
-		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
-		       HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
-		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
-		       HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
-		       HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
-	}
-
-	if (ASIC_IS_DCE32(rdev)) {
-		dce3_2_afmt_write_speaker_allocation(encoder);
-		dce3_2_afmt_write_sad_regs(encoder);
-	}
+	WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
+	       HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
+	       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
+	       HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
+	       HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
 
 	WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
 	       HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index 59d56dc..7bc3605 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -1214,7 +1214,7 @@ static struct radeon_asic rv770_asic = {
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.hdmi_enable = &r600_hdmi_enable,
-		.hdmi_setmode = &r600_hdmi_setmode,
+		.hdmi_setmode = &dce3_1_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &r600_copy_cpdma,
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 5646f9d..deb8496 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -391,6 +391,11 @@ void r600_rlc_stop(struct radeon_device *rdev);
 int r600_audio_init(struct radeon_device *rdev);
 struct r600_audio_pin r600_audio_status(struct radeon_device *rdev);
 void r600_audio_fini(struct radeon_device *rdev);
+void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock);
+void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer,
+				    size_t size);
+void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock);
+void r600_hdmi_audio_workaround(struct drm_encoder *encoder);
 int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
 void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
 void r600_hdmi_enable(struct drm_encoder *encoder, bool enable);
@@ -463,6 +468,8 @@ int rv770_copy_dma(struct radeon_device *rdev,
 u32 rv770_get_xclk(struct radeon_device *rdev);
 int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 int rv770_get_temp(struct radeon_device *rdev);
+/* hdmi */
+void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
 /* rv7xx pm */
 int rv770_dpm_init(struct radeon_device *rdev);
 int rv770_dpm_enable(struct radeon_device *rdev);
-- 
1.8.4.5

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [deathsimple/drm-next-3.16][PATCH V3 2/4] drm/radeon/hdmi: DCE3: clean ACR control
  2014-05-16  9:10 ` [deathsimple/drm-next-3.16][PATCH V3 2/4] drm/radeon/hdmi: DCE3: clean ACR control Rafał Miłecki
@ 2014-05-16 22:00   ` Alex Deucher
  2014-05-16 23:34     ` Rafał Miłecki
  0 siblings, 1 reply; 12+ messages in thread
From: Alex Deucher @ 2014-05-16 22:00 UTC (permalink / raw)
  To: Rafał Miłecki; +Cc: Maling list - DRI developers

On Fri, May 16, 2014 at 5:10 AM, Rafał Miłecki <zajec5@gmail.com> wrote:
> What initially seemed to be a typo in fglrx (using register 0x740c
> instead of 0x74dc) appeared to be a correct behavior. DCE3 has ACR and
> CRC registers swapped which explains why we needed
> WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
>
> This has been tested for possible regressions on DCE3 HD3470 (RV620).
>
> Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
> ---
> V2: Use defines for swapped regs, update commit message.
> ---
>  drivers/gpu/drm/radeon/r600_hdmi.c | 8 +++++---
>  drivers/gpu/drm/radeon/r600d.h     | 2 ++
>  2 files changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
> index b8b2efa..a828222e 100644
> --- a/drivers/gpu/drm/radeon/r600_hdmi.c
> +++ b/drivers/gpu/drm/radeon/r600_hdmi.c
> @@ -332,6 +332,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
>         u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
>         struct hdmi_avi_infoframe frame;
>         uint32_t offset;
> +       uint32_t acr_ctl;
>         ssize_t err;
>
>         if (!dig || !dig->afmt)
> @@ -351,15 +352,16 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
>         WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
>                HDMI0_NULL_SEND); /* send null packets when required */
>
> -       WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
> -
>         WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
>                HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
>                HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
>                HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
>                HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
>
> -       WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
> +       /* DCE 3.0 uses register that's normally for CRC_CONTROL */
> +       acr_ctl = ASIC_IS_DCE3(rdev) ? DCE3_HDMI0_ACR_PACKET_CONTROL :
> +                                      HDMI0_ACR_PACKET_CONTROL;
> +       WREG32(acr_ctl + offset,
>                HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
>                HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
>
> diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
> index 37455f6..10380c5 100644
> --- a/drivers/gpu/drm/radeon/r600d.h
> +++ b/drivers/gpu/drm/radeon/r600d.h
> @@ -1038,6 +1038,7 @@
>  #       define HDMI0_AZ_FORMAT_WTRIG_ACK   (1 << 29)
>  #define HDMI0_AUDIO_CRC_CONTROL      0x740c
>  #       define HDMI0_AUDIO_CRC_EN    (1 << 0)
> +#define DCE3_HDMI0_ACR_PACKET_CONTROL  0x740c
>  #define HDMI0_VBI_PACKET_CONTROL     0x7410
>  #       define HDMI0_NULL_SEND       (1 << 0)
>  #       define HDMI0_GC_SEND         (1 << 4)
> @@ -1166,6 +1167,7 @@
>  #       define HDMI0_ACR_48          3
>  #       define HDMI0_ACR_SOURCE      (1 << 8) /* 0 - hw; 1 - cts value */
>  #       define HDMI0_ACR_AUTO_SEND   (1 << 12)
> +#define DCE3_HDMI0_AUDIO_CRC_CONTROL   0x74dc

They aren't swapped in hw, the register defines were just accidentally
swapped in the header (probably a copy paste typo).  Just swap the
defines.  No need to keep the old values.

Alex

>  #define HDMI0_RAMP_CONTROL0          0x74e0
>  #       define HDMI0_RAMP_MAX_COUNT(x)   (((x) & 0xffffff) << 0)
>  #define HDMI0_RAMP_CONTROL1          0x74e4
> --
> 1.8.4.5
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [deathsimple/drm-next-3.16][PATCH V3 2/4] drm/radeon/hdmi: DCE3: clean ACR control
  2014-05-16 22:00   ` Alex Deucher
@ 2014-05-16 23:34     ` Rafał Miłecki
  2014-05-17  0:14       ` Rafał Miłecki
  0 siblings, 1 reply; 12+ messages in thread
From: Rafał Miłecki @ 2014-05-16 23:34 UTC (permalink / raw)
  To: Alex Deucher; +Cc: Maling list - DRI developers

On 17 May 2014 00:00, Alex Deucher <alexdeucher@gmail.com> wrote:
> On Fri, May 16, 2014 at 5:10 AM, Rafał Miłecki <zajec5@gmail.com> wrote:
>> +#define DCE3_HDMI0_AUDIO_CRC_CONTROL   0x74dc
>
> They aren't swapped in hw, the register defines were just accidentally
> swapped in the header (probably a copy paste typo).  Just swap the
> defines.  No need to keep the old values.

Are you sure about this? I've doubts because fglrx indeed uses
0x74dc for DCE2
0x740c for DCE3

Previously you wrote: "On DCE3, they should be ...".

I suspect we may still need old defines to support DCE2.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [deathsimple/drm-next-3.16][PATCH V3 2/4] drm/radeon/hdmi: DCE3: clean ACR control
  2014-05-16 23:34     ` Rafał Miłecki
@ 2014-05-17  0:14       ` Rafał Miłecki
  2014-05-17  0:15         ` Rafał Miłecki
  0 siblings, 1 reply; 12+ messages in thread
From: Rafał Miłecki @ 2014-05-17  0:14 UTC (permalink / raw)
  To: Alex Deucher; +Cc: Maling list - DRI developers

On 17 May 2014 01:34, Rafał Miłecki <zajec5@gmail.com> wrote:
> On 17 May 2014 00:00, Alex Deucher <alexdeucher@gmail.com> wrote:
>> On Fri, May 16, 2014 at 5:10 AM, Rafał Miłecki <zajec5@gmail.com> wrote:
>>> +#define DCE3_HDMI0_AUDIO_CRC_CONTROL   0x74dc
>>
>> They aren't swapped in hw, the register defines were just accidentally
>> swapped in the header (probably a copy paste typo).  Just swap the
>> defines.  No need to keep the old values.
>
> Are you sure about this? I've doubts because fglrx indeed uses
> 0x74dc for DCE2
> 0x740c for DCE3
>
> Previously you wrote: "On DCE3, they should be ...".
>
> I suspect we may still need old defines to support DCE2.

I was right. I've just compiled radeon with:
acr_ctl = 0x740c;
and tested it on DCE2. Audio didn't work.

Some debugging:
# avivotool regsrange 0x740c 0x740c
0000740c 00001100 (4352)
# avivotool regsrange 0x74dc 0x74dc
000074dc 00000000 (0)

As expected, audio was fixed by exeuting:
# avivotool regset 0x74dc 0x00001100

So it's the fact:
DCE2 uses 0x74dc
DCE2 uses 0x740c

So I believe my patch is OK.

-- 
Rafał
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [deathsimple/drm-next-3.16][PATCH V3 2/4] drm/radeon/hdmi: DCE3: clean ACR control
  2014-05-17  0:14       ` Rafał Miłecki
@ 2014-05-17  0:15         ` Rafał Miłecki
  2014-05-17 15:11           ` Alex Deucher
  0 siblings, 1 reply; 12+ messages in thread
From: Rafał Miłecki @ 2014-05-17  0:15 UTC (permalink / raw)
  To: Alex Deucher; +Cc: Maling list - DRI developers

On 17 May 2014 02:14, Rafał Miłecki <zajec5@gmail.com> wrote:
> So it's the fact:
> DCE2 uses 0x74dc
> DCE2 uses 0x740c

I meant:
DCE2 uses 0x74dc
DCE3 uses 0x740c
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [deathsimple/drm-next-3.16][PATCH V3 2/4] drm/radeon/hdmi: DCE3: clean ACR control
  2014-05-17  0:15         ` Rafał Miłecki
@ 2014-05-17 15:11           ` Alex Deucher
  0 siblings, 0 replies; 12+ messages in thread
From: Alex Deucher @ 2014-05-17 15:11 UTC (permalink / raw)
  To: Rafał Miłecki; +Cc: Maling list - DRI developers

On Fri, May 16, 2014 at 8:15 PM, Rafał Miłecki <zajec5@gmail.com> wrote:
> On 17 May 2014 02:14, Rafał Miłecki <zajec5@gmail.com> wrote:
>> So it's the fact:
>> DCE2 uses 0x74dc
>> DCE2 uses 0x740c
>
> I meant:
> DCE2 uses 0x74dc
> DCE3 uses 0x740c

Yeah, I just double checked DCE2 and you are correct.  So the patch is
fine as is.

Alex
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [deathsimple/drm-next-3.16][PATCH V4 1/4] drm/radeon/hdmi: use separated file for DCE 3.1/3.2 code
  2014-05-16  9:36 ` [deathsimple/drm-next-3.16][PATCH V4 " Rafał Miłecki
@ 2014-05-19 15:27   ` Alex Deucher
  0 siblings, 0 replies; 12+ messages in thread
From: Alex Deucher @ 2014-05-19 15:27 UTC (permalink / raw)
  To: Rafał Miłecki; +Cc: Maling list - DRI developers

On Fri, May 16, 2014 at 5:36 AM, Rafał Miłecki <zajec5@gmail.com> wrote:
> DCE 3.1 and 3.2 should be programmed in a different way than DCE 2 and
> DCE 3. The order of setting registers and sets of registers are
> different.
> It's still unsure how we will handle DCE 3.1 vs. DCE 3.2, since they
> have few differences as well.
> For now separate DCE 2 and DCE 3 path, so we can work on it without a
> risk of breaking DCE 3.1+.
>
> This has been tested for possible regressions on DCE32 HD4550 (RV710).
>
> Signed-off-by: Rafał Miłecki <zajec5@gmail.com>

Added the series to my 3.16 queue.

Alex

> ---
> V4: Add Copyright header. Alex is an author of
>     dce3_2_afmt_write_speaker_allocation
>     dce3_2_afmt_write_sad_regs
>     and I'm pretty much an author of
>     dce3_1_hdmi_setmode
> ---
>  drivers/gpu/drm/radeon/Makefile      |   2 +-
>  drivers/gpu/drm/radeon/dce3_1_afmt.c | 244 +++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/radeon/r600_hdmi.c   | 149 ++-------------------
>  drivers/gpu/drm/radeon/radeon_asic.c |   2 +-
>  drivers/gpu/drm/radeon/radeon_asic.h |   7 +
>  5 files changed, 263 insertions(+), 141 deletions(-)
>  create mode 100644 drivers/gpu/drm/radeon/dce3_1_afmt.c
>
> diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
> index 0943353..dbcbfe8 100644
> --- a/drivers/gpu/drm/radeon/Makefile
> +++ b/drivers/gpu/drm/radeon/Makefile
> @@ -72,7 +72,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
>         radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
>         rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
>         r200.o radeon_legacy_tv.o r600_cs.o r600_blit_shaders.o \
> -       radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
> +       radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o dce3_1_afmt.o \
>         evergreen.o evergreen_cs.o evergreen_blit_shaders.o \
>         evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \
>         atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \
> diff --git a/drivers/gpu/drm/radeon/dce3_1_afmt.c b/drivers/gpu/drm/radeon/dce3_1_afmt.c
> new file mode 100644
> index 0000000..51800e3
> --- /dev/null
> +++ b/drivers/gpu/drm/radeon/dce3_1_afmt.c
> @@ -0,0 +1,244 @@
> +/*
> + * Copyright 2013 Advanced Micro Devices, Inc.
> + * Copyright 2014 Rafał Miłecki
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
> +#include <linux/hdmi.h>
> +#include <drm/drmP.h>
> +#include "radeon.h"
> +#include "radeon_asic.h"
> +#include "r600d.h"
> +
> +static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
> +{
> +       struct radeon_device *rdev = encoder->dev->dev_private;
> +       struct drm_connector *connector;
> +       struct radeon_connector *radeon_connector = NULL;
> +       u32 tmp;
> +       u8 *sadb;
> +       int sad_count;
> +
> +       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
> +               if (connector->encoder == encoder) {
> +                       radeon_connector = to_radeon_connector(connector);
> +                       break;
> +               }
> +       }
> +
> +       if (!radeon_connector) {
> +               DRM_ERROR("Couldn't find encoder's connector\n");
> +               return;
> +       }
> +
> +       sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
> +       if (sad_count < 0) {
> +               DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
> +               return;
> +       }
> +
> +       /* program the speaker allocation */
> +       tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
> +       tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
> +       /* set HDMI mode */
> +       tmp |= HDMI_CONNECTION;
> +       if (sad_count)
> +               tmp |= SPEAKER_ALLOCATION(sadb[0]);
> +       else
> +               tmp |= SPEAKER_ALLOCATION(5); /* stereo */
> +       WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
> +
> +       kfree(sadb);
> +}
> +
> +static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder)
> +{
> +       struct radeon_device *rdev = encoder->dev->dev_private;
> +       struct drm_connector *connector;
> +       struct radeon_connector *radeon_connector = NULL;
> +       struct cea_sad *sads;
> +       int i, sad_count;
> +
> +       static const u16 eld_reg_to_type[][2] = {
> +               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
> +               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
> +               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR2, HDMI_AUDIO_CODING_TYPE_MPEG1 },
> +               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR3, HDMI_AUDIO_CODING_TYPE_MP3 },
> +               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR4, HDMI_AUDIO_CODING_TYPE_MPEG2 },
> +               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR5, HDMI_AUDIO_CODING_TYPE_AAC_LC },
> +               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR6, HDMI_AUDIO_CODING_TYPE_DTS },
> +               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR7, HDMI_AUDIO_CODING_TYPE_ATRAC },
> +               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR9, HDMI_AUDIO_CODING_TYPE_EAC3 },
> +               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR10, HDMI_AUDIO_CODING_TYPE_DTS_HD },
> +               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR11, HDMI_AUDIO_CODING_TYPE_MLP },
> +               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
> +       };
> +
> +       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
> +               if (connector->encoder == encoder) {
> +                       radeon_connector = to_radeon_connector(connector);
> +                       break;
> +               }
> +       }
> +
> +       if (!radeon_connector) {
> +               DRM_ERROR("Couldn't find encoder's connector\n");
> +               return;
> +       }
> +
> +       sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
> +       if (sad_count < 0) {
> +               DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
> +               return;
> +       }
> +       BUG_ON(!sads);
> +
> +       for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
> +               u32 value = 0;
> +               u8 stereo_freqs = 0;
> +               int max_channels = -1;
> +               int j;
> +
> +               for (j = 0; j < sad_count; j++) {
> +                       struct cea_sad *sad = &sads[j];
> +
> +                       if (sad->format == eld_reg_to_type[i][1]) {
> +                               if (sad->channels > max_channels) {
> +                                       value = MAX_CHANNELS(sad->channels) |
> +                                               DESCRIPTOR_BYTE_2(sad->byte2) |
> +                                               SUPPORTED_FREQUENCIES(sad->freq);
> +                                       max_channels = sad->channels;
> +                               }
> +
> +                               if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM)
> +                                       stereo_freqs |= sad->freq;
> +                               else
> +                                       break;
> +                       }
> +               }
> +
> +               value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs);
> +
> +               WREG32(eld_reg_to_type[i][0], value);
> +       }
> +
> +       kfree(sads);
> +}
> +
> +/*
> + * update the info frames with the data from the current display mode
> + */
> +void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
> +{
> +       struct drm_device *dev = encoder->dev;
> +       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;
> +       u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
> +       struct hdmi_avi_infoframe frame;
> +       uint32_t offset;
> +       ssize_t err;
> +
> +       if (!dig || !dig->afmt)
> +               return;
> +
> +       /* Silent, r600_hdmi_enable will raise WARN for us */
> +       if (!dig->afmt->enabled)
> +               return;
> +       offset = dig->afmt->offset;
> +
> +       /* disable audio prior to setting up hw */
> +       dig->afmt->pin = r600_audio_get_pin(rdev);
> +       r600_audio_enable(rdev, dig->afmt->pin, false);
> +
> +       r600_audio_set_dto(encoder, mode->clock);
> +
> +       WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
> +              HDMI0_NULL_SEND); /* send null packets when required */
> +
> +       WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
> +
> +       if (ASIC_IS_DCE32(rdev)) {
> +               WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
> +                      HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
> +                      HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
> +               WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
> +                      AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */
> +                      AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
> +       } else {
> +               WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
> +                      HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
> +                      HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
> +                      HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
> +                      HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
> +       }
> +
> +       if (ASIC_IS_DCE32(rdev)) {
> +               dce3_2_afmt_write_speaker_allocation(encoder);
> +               dce3_2_afmt_write_sad_regs(encoder);
> +       }
> +
> +       WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
> +              HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
> +              HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
> +
> +       WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
> +              HDMI0_NULL_SEND | /* send null packets when required */
> +              HDMI0_GC_SEND | /* send general control packets */
> +              HDMI0_GC_CONT); /* send general control packets every frame */
> +
> +       /* TODO: HDMI0_AUDIO_INFO_UPDATE */
> +       WREG32(HDMI0_INFOFRAME_CONTROL0 + offset,
> +              HDMI0_AVI_INFO_SEND | /* enable AVI info frames */
> +              HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */
> +              HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
> +              HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */
> +
> +       WREG32(HDMI0_INFOFRAME_CONTROL1 + offset,
> +              HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */
> +              HDMI0_AUDIO_INFO_LINE(2)); /* anything other than 0 */
> +
> +       WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */
> +
> +       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +       if (err < 0) {
> +               DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
> +               return;
> +       }
> +
> +       err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
> +       if (err < 0) {
> +               DRM_ERROR("failed to pack AVI infoframe: %zd\n", err);
> +               return;
> +       }
> +
> +       r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer));
> +       r600_hdmi_update_ACR(encoder, mode->clock);
> +
> +       /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
> +       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);
> +
> +       /* enable audio after to setting up hw */
> +       r600_audio_enable(rdev, dig->afmt->pin, true);
> +}
> diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
> index 85a2bb2..b8b2efa 100644
> --- a/drivers/gpu/drm/radeon/r600_hdmi.c
> +++ b/drivers/gpu/drm/radeon/r600_hdmi.c
> @@ -133,7 +133,7 @@ struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock)
>  /*
>   * update the N and CTS parameters for a given pixel clock rate
>   */
> -static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
> +void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
>  {
>         struct drm_device *dev = encoder->dev;
>         struct radeon_device *rdev = dev->dev_private;
> @@ -155,8 +155,8 @@ static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
>  /*
>   * build a HDMI Video Info Frame
>   */
> -static void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
> -                                          void *buffer, size_t size)
> +void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer,
> +                                   size_t size)
>  {
>         struct drm_device *dev = encoder->dev;
>         struct radeon_device *rdev = dev->dev_private;
> @@ -231,7 +231,7 @@ int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder)
>  /*
>   * write the audio workaround status to the hardware
>   */
> -static void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
> +void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
>  {
>         struct drm_device *dev = encoder->dev;
>         struct radeon_device *rdev = dev->dev_private;
> @@ -250,7 +250,7 @@ static void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
>                  value, ~HDMI0_AUDIO_TEST_EN);
>  }
>
> -static void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
> +void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
>  {
>         struct drm_device *dev = encoder->dev;
>         struct radeon_device *rdev = dev->dev_private;
> @@ -320,121 +320,6 @@ static void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
>         }
>  }
>
> -static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
> -{
> -       struct radeon_device *rdev = encoder->dev->dev_private;
> -       struct drm_connector *connector;
> -       struct radeon_connector *radeon_connector = NULL;
> -       u32 tmp;
> -       u8 *sadb;
> -       int sad_count;
> -
> -       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
> -               if (connector->encoder == encoder) {
> -                       radeon_connector = to_radeon_connector(connector);
> -                       break;
> -               }
> -       }
> -
> -       if (!radeon_connector) {
> -               DRM_ERROR("Couldn't find encoder's connector\n");
> -               return;
> -       }
> -
> -       sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
> -       if (sad_count < 0) {
> -               DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
> -               return;
> -       }
> -
> -       /* program the speaker allocation */
> -       tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
> -       tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
> -       /* set HDMI mode */
> -       tmp |= HDMI_CONNECTION;
> -       if (sad_count)
> -               tmp |= SPEAKER_ALLOCATION(sadb[0]);
> -       else
> -               tmp |= SPEAKER_ALLOCATION(5); /* stereo */
> -       WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
> -
> -       kfree(sadb);
> -}
> -
> -static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder)
> -{
> -       struct radeon_device *rdev = encoder->dev->dev_private;
> -       struct drm_connector *connector;
> -       struct radeon_connector *radeon_connector = NULL;
> -       struct cea_sad *sads;
> -       int i, sad_count;
> -
> -       static const u16 eld_reg_to_type[][2] = {
> -               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
> -               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
> -               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR2, HDMI_AUDIO_CODING_TYPE_MPEG1 },
> -               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR3, HDMI_AUDIO_CODING_TYPE_MP3 },
> -               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR4, HDMI_AUDIO_CODING_TYPE_MPEG2 },
> -               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR5, HDMI_AUDIO_CODING_TYPE_AAC_LC },
> -               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR6, HDMI_AUDIO_CODING_TYPE_DTS },
> -               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR7, HDMI_AUDIO_CODING_TYPE_ATRAC },
> -               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR9, HDMI_AUDIO_CODING_TYPE_EAC3 },
> -               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR10, HDMI_AUDIO_CODING_TYPE_DTS_HD },
> -               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR11, HDMI_AUDIO_CODING_TYPE_MLP },
> -               { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
> -       };
> -
> -       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
> -               if (connector->encoder == encoder) {
> -                       radeon_connector = to_radeon_connector(connector);
> -                       break;
> -               }
> -       }
> -
> -       if (!radeon_connector) {
> -               DRM_ERROR("Couldn't find encoder's connector\n");
> -               return;
> -       }
> -
> -       sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
> -       if (sad_count < 0) {
> -               DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
> -               return;
> -       }
> -       BUG_ON(!sads);
> -
> -       for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
> -               u32 value = 0;
> -               u8 stereo_freqs = 0;
> -               int max_channels = -1;
> -               int j;
> -
> -               for (j = 0; j < sad_count; j++) {
> -                       struct cea_sad *sad = &sads[j];
> -
> -                       if (sad->format == eld_reg_to_type[i][1]) {
> -                               if (sad->channels > max_channels) {
> -                                       value = MAX_CHANNELS(sad->channels) |
> -                                               DESCRIPTOR_BYTE_2(sad->byte2) |
> -                                               SUPPORTED_FREQUENCIES(sad->freq);
> -                                       max_channels = sad->channels;
> -                               }
> -
> -                               if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM)
> -                                       stereo_freqs |= sad->freq;
> -                               else
> -                                       break;
> -                       }
> -               }
> -
> -               value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs);
> -
> -               WREG32(eld_reg_to_type[i][0], value);
> -       }
> -
> -       kfree(sads);
> -}
> -
>  /*
>   * update the info frames with the data from the current display mode
>   */
> @@ -468,25 +353,11 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
>
>         WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
>
> -       if (ASIC_IS_DCE32(rdev)) {
> -               WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
> -                      HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
> -                      HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
> -               WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
> -                      AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */
> -                      AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
> -       } else {
> -               WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
> -                      HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
> -                      HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
> -                      HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
> -                      HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
> -       }
> -
> -       if (ASIC_IS_DCE32(rdev)) {
> -               dce3_2_afmt_write_speaker_allocation(encoder);
> -               dce3_2_afmt_write_sad_regs(encoder);
> -       }
> +       WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
> +              HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
> +              HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
> +              HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
> +              HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
>
>         WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
>                HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
> diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
> index 59d56dc..7bc3605 100644
> --- a/drivers/gpu/drm/radeon/radeon_asic.c
> +++ b/drivers/gpu/drm/radeon/radeon_asic.c
> @@ -1214,7 +1214,7 @@ static struct radeon_asic rv770_asic = {
>                 .set_backlight_level = &atombios_set_backlight_level,
>                 .get_backlight_level = &atombios_get_backlight_level,
>                 .hdmi_enable = &r600_hdmi_enable,
> -               .hdmi_setmode = &r600_hdmi_setmode,
> +               .hdmi_setmode = &dce3_1_hdmi_setmode,
>         },
>         .copy = {
>                 .blit = &r600_copy_cpdma,
> diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
> index 5646f9d..deb8496 100644
> --- a/drivers/gpu/drm/radeon/radeon_asic.h
> +++ b/drivers/gpu/drm/radeon/radeon_asic.h
> @@ -391,6 +391,11 @@ void r600_rlc_stop(struct radeon_device *rdev);
>  int r600_audio_init(struct radeon_device *rdev);
>  struct r600_audio_pin r600_audio_status(struct radeon_device *rdev);
>  void r600_audio_fini(struct radeon_device *rdev);
> +void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock);
> +void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer,
> +                                   size_t size);
> +void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock);
> +void r600_hdmi_audio_workaround(struct drm_encoder *encoder);
>  int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
>  void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
>  void r600_hdmi_enable(struct drm_encoder *encoder, bool enable);
> @@ -463,6 +468,8 @@ int rv770_copy_dma(struct radeon_device *rdev,
>  u32 rv770_get_xclk(struct radeon_device *rdev);
>  int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
>  int rv770_get_temp(struct radeon_device *rdev);
> +/* hdmi */
> +void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
>  /* rv7xx pm */
>  int rv770_dpm_init(struct radeon_device *rdev);
>  int rv770_dpm_enable(struct radeon_device *rdev);
> --
> 1.8.4.5
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2014-05-19 15:27 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-16  9:10 [deathsimple/drm-next-3.16][PATCH V3 1/4] drm/radeon/hdmi: use separated file for DCE 3.1/3.2 code Rafał Miłecki
2014-05-16  9:10 ` [deathsimple/drm-next-3.16][PATCH V3 2/4] drm/radeon/hdmi: DCE3: clean ACR control Rafał Miłecki
2014-05-16 22:00   ` Alex Deucher
2014-05-16 23:34     ` Rafał Miłecki
2014-05-17  0:14       ` Rafał Miłecki
2014-05-17  0:15         ` Rafał Miłecki
2014-05-17 15:11           ` Alex Deucher
2014-05-16  9:10 ` [deathsimple/drm-next-3.16][PATCH V3 3/4] drm/radeon/hdmi: DCE2: update setmode Rafał Miłecki
2014-05-16  9:10 ` [deathsimple/drm-next-3.16][PATCH V3 4/4] drm/radeon/hdmi: DCE2: simplify audio workaround Rafał Miłecki
2014-05-16  9:22 ` [deathsimple/drm-next-3.16][PATCH V3 1/4] drm/radeon/hdmi: use separated file for DCE 3.1/3.2 code Christian König
2014-05-16  9:36 ` [deathsimple/drm-next-3.16][PATCH V4 " Rafał Miłecki
2014-05-19 15:27   ` Alex Deucher

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox