* [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* 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
* [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 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