Mailinglist Archive: radeonhd (427 mails)

< Previous Next >
[radeonhd] RS690 HDMI Audio support
Hi everybody,

attached is the last status of the RS690 HDMI Audio patch.
Its based on a patch from Christiaan van Dijk, just stripped down the
bare minimum necessary. Sorry for the delay, but i'm very busy atm, and
will properly be till the end of this summer.

Bye,
Christian.
From 9e7dd12d1cf263e2d29b535b816035443201bd9d Mon Sep 17 00:00:00 2001
From: Christian Koenig <deathsimple@xxxxxxxxxxx>
Date: Wed, 13 May 2009 22:20:09 +0200
Subject: [PATCH] Initial RS690 HDMI Audio support.

Based on a patch from Christiaan van Dijk, but stripped down the bare minimum.
---
src/rhd_audio.c | 18 +++++++-----------
src/rhd_hdmi.c | 42 ++++++++++++++++++++++++++++++------------
src/rhd_hdmi.h | 2 +-
src/rhd_output.c | 38 ++++++++++++++++++++++++++++++++++++++
src/rhd_output.h | 1 +
src/rhd_regs.h | 5 ++++-
6 files changed, 81 insertions(+), 25 deletions(-)

diff --git a/src/rhd_audio.c b/src/rhd_audio.c
index 8d8a7d1..7223f83 100644
--- a/src/rhd_audio.c
+++ b/src/rhd_audio.c
@@ -241,28 +241,22 @@ RHDAudioSetClock(RHDPtr rhdPtr, struct rhdOutput* Output,
CARD32 Clock)
break;

default:
+ xf86DrvMsg(Audio->scrnIndex, X_ERROR, "%s: unsupported output
type\n", __func__);
break;
}

- switch(Output->Id) {
- case RHD_OUTPUT_TMDSA:
- case RHD_OUTPUT_UNIPHYA:
+ switch(RHDOutputTmdsIndex(Output)) {
+ case 0:
RHDRegWrite(Audio, AUDIO_PLL1_MUL, Rate*50);
RHDRegWrite(Audio, AUDIO_PLL1_DIV, Clock*100);
RHDRegWrite(Audio, AUDIO_CLK_SRCSEL, 0);
break;

- case RHD_OUTPUT_LVTMA:
- case RHD_OUTPUT_UNIPHYB:
- case RHD_OUTPUT_KLDSKP_LVTMA:
+ case 1:
RHDRegWrite(Audio, AUDIO_PLL2_MUL, Rate*50);
RHDRegWrite(Audio, AUDIO_PLL2_DIV, Clock*100);
RHDRegWrite(Audio, AUDIO_CLK_SRCSEL, 1);
break;
-
- default:
- xf86DrvMsg(Audio->scrnIndex, X_ERROR, "%s: unsupported output
type\n", __func__);
- break;
}
}

@@ -375,7 +369,9 @@ RHDAudioRestore(RHDPtr rhdPtr)
return;
}

- /* shoutdown the audio engine before doing anything else */
+ /*
+ * Shutdown the audio engine before doing anything else.
+ */
RHDAudioSetEnable(rhdPtr, FALSE);

RHDRegWrite(Audio, AUDIO_TIMING, Audio->StoreTiming);
diff --git a/src/rhd_hdmi.c b/src/rhd_hdmi.c
index 9a52536..cf3e8b1 100644
--- a/src/rhd_hdmi.c
+++ b/src/rhd_hdmi.c
@@ -234,9 +234,13 @@ HdmiAudioInfoFrame(
static void
HdmiAudioDebugWorkaround(struct rhdHdmi* hdmi, Bool Enable)
{
+ RHDRegWrite(hdmi, hdmi->Offset+HDMI_AUDIO_DEBUG_0, 0x00FFFFFF);
+ RHDRegWrite(hdmi, hdmi->Offset+HDMI_AUDIO_DEBUG_1, 0x007FFFFF);
+ RHDRegWrite(hdmi, hdmi->Offset+HDMI_AUDIO_DEBUG_2, 0x00000001);
+ RHDRegWrite(hdmi, hdmi->Offset+HDMI_AUDIO_DEBUG_3, 0x00000001);
+
if(Enable) {
RHDRegMask(hdmi, hdmi->Offset+HDMI_CNTL, 0x1000, 0x1000);
- RHDRegWrite(hdmi, hdmi->Offset+HDMI_AUDIO_DEBUG, 0xffffff);
} else {
RHDRegMask(hdmi, hdmi->Offset+HDMI_CNTL, 0, 0x1000);
}
@@ -253,17 +257,21 @@ RHDHdmiInit(RHDPtr rhdPtr, struct rhdOutput* Output)
struct rhdHdmi *hdmi;
RHDFUNC(rhdPtr);

- if(rhdPtr->ChipSet >= RHD_R600) {
+ if(rhdPtr->ChipSet >= RHD_RS600) {
hdmi = (struct rhdHdmi *) xnfcalloc(sizeof(struct rhdHdmi), 1);
hdmi->scrnIndex = rhdPtr->scrnIndex;
hdmi->Output = Output;
+
switch(Output->Id) {
case RHD_OUTPUT_TMDSA:
hdmi->Offset = HDMI_TMDS;
break;

case RHD_OUTPUT_LVTMA:
- hdmi->Offset = HDMI_LVTMA;
+ if(RHDOutputTmdsIndex(Output) == 0)
+ hdmi->Offset = HDMI_TMDS;
+ else
+ hdmi->Offset = HDMI_LVTMA;
break;

case RHD_OUTPUT_UNIPHYA:
@@ -309,6 +317,7 @@ RHDHdmiSetMode(struct rhdHdmi *hdmi, DisplayModePtr Mode)
HdmiAudioClockRegeneration(hdmi, Mode->Clock);

RHDRegWrite(hdmi, hdmi->Offset+HDMI_VIDEOCNTL, 0x13);
+
RHDRegWrite(hdmi, hdmi->Offset+HDMI_VERSION, 0x202);

HdmiVideoInfoFrame(hdmi, RGB, FALSE, 0, 0, 0,
@@ -322,7 +331,7 @@ RHDHdmiSetMode(struct rhdHdmi *hdmi, DisplayModePtr Mode)
}

/*
- * update settings whith current parameters from audio engine
+ * update settings with current parameters from audio engine
*/
void
RHDHdmiUpdateAudioSettings(
@@ -382,9 +391,11 @@ RHDHdmiUpdateAudioSettings(

RHDRegMask(hdmi, hdmi->Offset+HDMI_IEC60958_2, iec, 0x5000f);

+ /* 0x021 or 0x031 sets the audio frame length */
RHDRegWrite(hdmi, hdmi->Offset+HDMI_AUDIOCNTL, 0x31);
HdmiAudioInfoFrame(hdmi, channels-1, 0, 0, 0, 0, 0, 0, FALSE);

+ /* RHDRegMask(hdmi, hdmi->Offset+HDMI_CNTL, 0x4000000, 0x4000000); */
RHDRegMask(hdmi, hdmi->Offset+HDMI_CNTL, 0x400000, 0x400000);
}

@@ -401,18 +412,19 @@ RHDHdmiEnable(struct rhdHdmi *hdmi, Bool Enable)
* so enabling/disabling HDMI was moved here for TMDSA and LVTMA */
switch(hdmi->Output->Id) {
case RHD_OUTPUT_TMDSA:
- RHDRegMask(hdmi, TMDSA_CNTL, Enable ? 0x4 : 0x0, 0x4);
- RHDRegWrite(hdmi, hdmi->Offset+HDMI_ENABLE, Enable ? 0x101 : 0x0);
- break;
+ RHDRegMask(hdmi, TMDSA_CNTL, Enable ? 0x4 : 0x0, 0x4);
+ RHDRegWrite(hdmi, hdmi->Offset+HDMI_ENABLE, Enable ? 0x101 : 0x0);
+ break;

case RHD_OUTPUT_LVTMA:
- RHDRegMask(hdmi, LVTMA_CNTL, Enable ? 0x4 : 0x0, 0x4);
- RHDRegWrite(hdmi, hdmi->Offset+HDMI_ENABLE, Enable ? 0x105 : 0x0);
- break;
+ RHDRegMask(hdmi, LVTMA_CNTL, Enable ? 0x4 : 0x0, 0x4);
+ RHDRegWrite(hdmi, hdmi->Offset+HDMI_ENABLE, Enable ? 0x105 : 0x0);
+ break;

case RHD_OUTPUT_UNIPHYA:
case RHD_OUTPUT_UNIPHYB:
case RHD_OUTPUT_KLDSKP_LVTMA:
+ /* This part is doubtfull in my opinion */
RHDRegWrite(hdmi, hdmi->Offset+HDMI_ENABLE, Enable ? 0x110 : 0x0);
break;

@@ -433,7 +445,10 @@ RHDHdmiSave(struct rhdHdmi *hdmi)

hdmi->StoreEnable = RHDRegRead(hdmi, hdmi->Offset+HDMI_ENABLE);
hdmi->StoreControl = RHDRegRead(hdmi, hdmi->Offset+HDMI_CNTL);
- hdmi->StoredAudioDebugWorkaround = RHDRegRead(hdmi,
hdmi->Offset+HDMI_AUDIO_DEBUG);
+ hdmi->StoredAudioDebugWorkaround[0x0] = RHDRegRead(hdmi,
hdmi->Offset+HDMI_AUDIO_DEBUG_0);
+ hdmi->StoredAudioDebugWorkaround[0x1] = RHDRegRead(hdmi,
hdmi->Offset+HDMI_AUDIO_DEBUG_1);
+ hdmi->StoredAudioDebugWorkaround[0x2] = RHDRegRead(hdmi,
hdmi->Offset+HDMI_AUDIO_DEBUG_2);
+ hdmi->StoredAudioDebugWorkaround[0x3] = RHDRegRead(hdmi,
hdmi->Offset+HDMI_AUDIO_DEBUG_3);

hdmi->StoredFrameVersion = RHDRegRead(hdmi, hdmi->Offset+HDMI_VERSION);

@@ -483,7 +498,10 @@ RHDHdmiRestore(struct rhdHdmi *hdmi)

RHDRegWrite(hdmi, hdmi->Offset+HDMI_ENABLE, hdmi->StoreEnable);
RHDRegWrite(hdmi, hdmi->Offset+HDMI_CNTL, hdmi->StoreControl);
- RHDRegWrite(hdmi, hdmi->Offset+HDMI_AUDIO_DEBUG,
hdmi->StoredAudioDebugWorkaround);
+ RHDRegWrite(hdmi, hdmi->Offset+HDMI_AUDIO_DEBUG_0,
hdmi->StoredAudioDebugWorkaround[0x0]);
+ RHDRegWrite(hdmi, hdmi->Offset+HDMI_AUDIO_DEBUG_1,
hdmi->StoredAudioDebugWorkaround[0x1]);
+ RHDRegWrite(hdmi, hdmi->Offset+HDMI_AUDIO_DEBUG_2,
hdmi->StoredAudioDebugWorkaround[0x2]);
+ RHDRegWrite(hdmi, hdmi->Offset+HDMI_AUDIO_DEBUG_3,
hdmi->StoredAudioDebugWorkaround[0x3]);

RHDRegWrite(hdmi, hdmi->Offset+HDMI_VERSION, hdmi->StoredFrameVersion);

diff --git a/src/rhd_hdmi.h b/src/rhd_hdmi.h
index 4229417..5b1e8f0 100644
--- a/src/rhd_hdmi.h
+++ b/src/rhd_hdmi.h
@@ -39,7 +39,7 @@ struct rhdHdmi {
CARD32 StoreEnable;
CARD32 StoreControl;
CARD32 StoreUnknown[0x3];
- CARD32 StoredAudioDebugWorkaround;
+ CARD32 StoredAudioDebugWorkaround[0x4];

CARD32 StoredFrameVersion;
CARD32 StoredVideoControl;
diff --git a/src/rhd_output.c b/src/rhd_output.c
index 7fe2ee9..d1fbde4 100644
--- a/src/rhd_output.c
+++ b/src/rhd_output.c
@@ -261,3 +261,41 @@ RHDOutputAttachConnector(struct rhdOutput *Output, struct
rhdConnector *Connecto
xf86DrvMsg(rhdPtr->scrnIndex, X_WARNING, "Failed to %s HDMI on
%s\n", val.Bool ? "disable" : "enable", Output->Name);
}
}
+
+/*
+ * Returns the TMDS index of the given output, important for HDMI/Audio setup
+ */
+int
+RHDOutputTmdsIndex(struct rhdOutput *Output)
+{
+ struct rhdOutput *i = RHDPTRI(Output)->Outputs;
+ int index;
+
+ switch(Output->Id) {
+ case RHD_OUTPUT_TMDSA:
+ case RHD_OUTPUT_UNIPHYA:
+ index=0;
+ break;
+
+ case RHD_OUTPUT_LVTMA:
+ /* special case check if an TMDSA is present */
+ index=0;
+ while(i) {
+ if(i->Id==RHD_OUTPUT_TMDSA)
+ index++;
+ i = i->Next;
+ }
+ break;
+
+ case RHD_OUTPUT_UNIPHYB:
+ case RHD_OUTPUT_KLDSKP_LVTMA:
+ index=1;
+ break;
+
+ default:
+ xf86DrvMsg(Output->scrnIndex, X_ERROR, "%s: unsupported output
type\n", __func__);
+ index=-1;
+ break;
+ }
+ return index;
+}
diff --git a/src/rhd_output.h b/src/rhd_output.h
index 22edfe9..21a49d2 100644
--- a/src/rhd_output.h
+++ b/src/rhd_output.h
@@ -115,6 +115,7 @@ void RHDOutputsRestore(RHDPtr rhdPtr);
void RHDOutputsDestroy(RHDPtr rhdPtr);
void RHDOutputPrintSensedType(struct rhdOutput *Output);
void RHDOutputAttachConnector(struct rhdOutput *Output, struct rhdConnector
*Connector);
+int RHDOutputTmdsIndex(struct rhdOutput *Output);

/* output local functions. */
struct rhdOutput *RHDDACAInit(RHDPtr rhdPtr);
diff --git a/src/rhd_regs.h b/src/rhd_regs.h
index bf74dd3..2209817 100644
--- a/src/rhd_regs.h
+++ b/src/rhd_regs.h
@@ -1113,7 +1113,10 @@ enum {
HDMI_IEC60958_1 = 0xd4,
HDMI_IEC60958_2 = 0xd8,
HDMI_UNKNOWN_2 = 0xdc,
- HDMI_AUDIO_DEBUG = 0xe0
+ HDMI_AUDIO_DEBUG_0 = 0xe0,
+ HDMI_AUDIO_DEBUG_1 = 0xe4,
+ HDMI_AUDIO_DEBUG_2 = 0xe8,
+ HDMI_AUDIO_DEBUG_3 = 0xec
};

#endif /* _RHD_REGS_H */
--
1.6.0.4

< Previous Next >
Follow Ups