Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 68706337 authored by Rafał Miłecki's avatar Rafał Miłecki Committed by Alex Deucher
Browse files

drm/radeon/hdmi: DCE2: update setmode

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: default avatarRafał Miłecki <zajec5@gmail.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 2e93cac9
Loading
Loading
Loading
Loading
+75 −37
Original line number Diff line number Diff line
@@ -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,
	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_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,
	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_AUTO_SEND, /* allow hw to sent ACR packets when required */
		 ~(HDMI0_ACR_SOURCE |
		   HDMI0_ACR_AUTO_SEND));

	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
	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 */

	/* TODO: HDMI0_AUDIO_INFO_UPDATE */
	WREG32(HDMI0_INFOFRAME_CONTROL0 + offset,
	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_CONT); /* send audio info frames every frame/field */
		  HDMI0_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */

	WREG32(HDMI0_INFOFRAME_CONTROL1 + offset,
	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_AUDIO_INFO_LINE(2), /* anything other than 0 */
		 ~(HDMI0_AVI_INFO_LINE_MASK |
		   HDMI0_AUDIO_INFO_LINE_MASK));

	WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */
	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);
+15 −0
Original line number Diff line number Diff line
@@ -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)