summaryrefslogtreecommitdiff
authorChristian K├Ânig <deathsimple@vodafone.de>2009-12-18 18:33:43 (GMT)
committer Matthias Hopf <mhopf@suse.de>2009-12-28 12:01:36 (GMT)
commitace8f44f6cbd7fd393b5a8a30468471ccee3726c (patch) (side-by-side diff)
tree18927d433b5b543a5130ed04f134c1cb3d1572c4
parentffc141e2b9adbcf94780b877bf0e4d93d83f41a7 (diff)
downloadxf86-video-radeonhd-ace8f44f6cbd7fd393b5a8a30468471ccee3726c.zip
xf86-video-radeonhd-ace8f44f6cbd7fd393b5a8a30468471ccee3726c.tar.gz
HDMI audio support for RV710 and RV730.
This patch adds audio support for the RV710 and RV730 chipsets. A special "Thank you" goes to Andrew Wasielewski, for finding the 0x7604 register dependency, submitting a bunch of logs and testing really a lot of different patches until we figured this out completely. Signed-off-by: Matthias Hopf <mhopf@suse.de>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--src/rhd_atomout.c39
-rw-r--r--src/rhd_audio.c12
-rw-r--r--src/rhd_dig.c29
-rw-r--r--src/rhd_hdmi.c37
-rw-r--r--src/rhd_output.c16
-rw-r--r--src/rhd_regs.h2
6 files changed, 90 insertions, 45 deletions
diff --git a/src/rhd_atomout.c b/src/rhd_atomout.c
index 5f3db26..9f879a8 100644
--- a/src/rhd_atomout.c
+++ b/src/rhd_atomout.c
@@ -808,7 +808,6 @@ rhdAtomOutputDestroy(struct rhdOutput *Output)
RHDFUNC(Output);
if (Private->Save)
xfree(Private->Save);
- RHDHdmiDestroy(Private->Hdmi);
if (Private)
xfree(Private);
@@ -864,30 +863,38 @@ RHDAtomOutputAllocFree(struct rhdOutput *Output, enum rhdOutputAllocation Alloc)
*/
if (Private->EncoderId != atomEncoderNone)
return TRUE;
+
if (Output->Id != RHD_OUTPUT_KLDSKP_LVTMA
&& !rhdPtr->DigEncoderOutput[0]) {
rhdPtr->DigEncoderOutput[0] = Output;
TransmitterConfig->Encoder = Private->EncoderId = atomEncoderDIG1;
xf86DrvMsg(Output->scrnIndex, X_INFO, "Mapping DIG1 encoder to %s\n",TransmitterName);
- return TRUE;
} else if (!rhdPtr->DigEncoderOutput[1]) {
rhdPtr->DigEncoderOutput[1] = Output;
TransmitterConfig->Encoder = Private->EncoderId = atomEncoderDIG2;
xf86DrvMsg(Output->scrnIndex, X_INFO, "Mapping DIG2 encoder to %s\n",TransmitterName);
- return TRUE;
} else
return FALSE;
+
+ Private->Hdmi = RHDHdmiInit(rhdPtr, Output);
+ RHDHdmiSave(Private->Hdmi);
+ RHDHdmiCommitAudioWorkaround(Private->Hdmi);
+ return TRUE;
+
case RHD_OUTPUT_FREE:
- TransmitterConfig->Encoder = Private->EncoderId = atomEncoderNone;
- if (rhdPtr->DigEncoderOutput[0] == Output) {
+ TransmitterConfig->Encoder = Private->EncoderId = atomEncoderNone;
+ if (rhdPtr->DigEncoderOutput[0] == Output)
rhdPtr->DigEncoderOutput[0] = NULL;
- return TRUE;
- } else if (rhdPtr->DigEncoderOutput[1] == Output) {
+ else if (rhdPtr->DigEncoderOutput[1] == Output)
rhdPtr->DigEncoderOutput[1] = NULL;
- return TRUE;
- } else
+ else
return FALSE;
- break;
+
+ RHDHdmiRestore(Private->Hdmi);
+ RHDHdmiDestroy(Private->Hdmi);
+ Private->Hdmi = NULL;
+ return TRUE;
+
default:
return FALSE;
}
@@ -963,6 +970,7 @@ RHDAtomOutputInit(RHDPtr rhdPtr, rhdConnectorType ConnectorType,
EncoderConfig = &Private->EncoderConfig;
Private->PixelClock = 0;
+ Private->Hdmi = NULL;
switch (OutputType) {
case RHD_OUTPUT_NONE:
@@ -973,13 +981,11 @@ RHDAtomOutputInit(RHDPtr rhdPtr, rhdConnectorType ConnectorType,
Output->Sense = RHDBIOSScratchDACSense;
Private->EncoderId = atomEncoderDACA;
Private->OutputControlId = atomDAC1Output;
- Private->Hdmi = NULL;
break;
case RHD_OUTPUT_DACB:
Output->Sense = RHDBIOSScratchDACSense;
Private->EncoderId = atomEncoderDACB;
Private->OutputControlId = atomDAC2Output;
- Private->Hdmi = NULL;
break;
case RHD_OUTPUT_TMDSA:
case RHD_OUTPUT_LVTMA:
@@ -1005,11 +1011,6 @@ RHDAtomOutputInit(RHDPtr rhdPtr, rhdConnectorType ConnectorType,
else
Private->DualLink = FALSE;
- if (ConnectorType != RHD_CONNECTOR_PANEL)
- Private->Hdmi = RHDHdmiInit(rhdPtr, Output);
- else
- Private->Hdmi = NULL;
-
Private->EncoderVersion = rhdAtomEncoderControlVersion(rhdPtr->atomBIOS, Private->EncoderId);
switch (Private->EncoderVersion.cref) {
case 1:
@@ -1092,12 +1093,10 @@ RHDAtomOutputInit(RHDPtr rhdPtr, rhdConnectorType ConnectorType,
if (ConnectorType == RHD_CONNECTOR_PANEL) {
TransmitterConfig->Mode = EncoderConfig->u.dig.EncoderMode = atomLVDS;
LVDSInfoRetrieve(Output, Private);
- Private->Hdmi = NULL;
} else {
TransmitterConfig->Mode = EncoderConfig->u.dig.EncoderMode = atomDVI;
TMDSInfoRetrieve(rhdPtr, Private);
Private->Coherent = FALSE;
- Private->Hdmi = RHDHdmiInit(rhdPtr, Output);
}
break;
@@ -1173,7 +1172,6 @@ RHDAtomOutputInit(RHDPtr rhdPtr, rhdConnectorType ConnectorType,
case RHD_CONNECTOR_DVI:
case RHD_CONNECTOR_DVI_SINGLE:
TransmitterConfig->Mode = EncoderConfig->u.dig.EncoderMode = atomDVI;
- Private->Hdmi = RHDHdmiInit(rhdPtr, Output);
break;
case RHD_CONNECTOR_PANEL:
TransmitterConfig->Mode = EncoderConfig->u.dig.EncoderMode = atomLVDS;
@@ -1271,7 +1269,6 @@ RhdAtomSetupBacklightControlProperty(struct rhdOutput *Output,
TransmitterConfig->Encoder = Private->EncoderId = atomEncoderNone;
LVDSInfoRetrieve(Output, Private);
Private->PixelClock = 0;
- Private->Hdmi = NULL;
break;
case RHD_OUTPUT_LVTMA:
Private->OutputControlId = atomLCDOutput;
diff --git a/src/rhd_audio.c b/src/rhd_audio.c
index 5e3c4e2..aac7d62 100644
--- a/src/rhd_audio.c
+++ b/src/rhd_audio.c
@@ -210,6 +210,14 @@ RHDAudioSetEnable(RHDPtr rhdPtr, Bool Enable)
AUDIO_BPS_16|AUDIO_BPS_20,
AUDIO_CODEC_PCM
);
+
+
+ if(RHDPTRI(Audio)->ChipSet >= RHD_R700)
+ {
+ /* another bit which use is unknown, but is needed at least on RV710 and RV730 to get audio working */
+ RHDRegMask(Audio, R700_AUDIO_UNKNOWN, 0x00000001, 0x00000001);
+ }
+
} else {
TimerFree(Audio->Timer);
Audio->Timer = NULL;
@@ -239,6 +247,10 @@ RHDAudioSetClock(RHDPtr rhdPtr, struct rhdOutput* Output, CARD32 Clock)
case RHD_OUTPUT_UNIPHYA:
case RHD_OUTPUT_UNIPHYB:
+ case RHD_OUTPUT_UNIPHYC:
+ case RHD_OUTPUT_UNIPHYD:
+ case RHD_OUTPUT_UNIPHYE:
+ case RHD_OUTPUT_UNIPHYF:
case RHD_OUTPUT_KLDSKP_LVTMA:
RHDRegMask(Audio, AUDIO_TIMING, 0x100, 0x301);
break;
diff --git a/src/rhd_dig.c b/src/rhd_dig.c
index 3458d4b..3156c37 100644
--- a/src/rhd_dig.c
+++ b/src/rhd_dig.c
@@ -1571,7 +1571,6 @@ DigDestroy(struct rhdOutput *Output)
Encoder->Destroy(Output);
Transmitter->Destroy(Output);
- RHDHdmiDestroy(Private->Hdmi);
if (Transmitter->PropertyPrivate)
RhdAtomDestroyBacklightControlProperty(Output, Transmitter->PropertyPrivate);
xfree(Private);
@@ -1620,7 +1619,6 @@ DigAllocFree(struct rhdOutput *Output, enum rhdOutputAllocation Alloc)
Private->EncoderID = ENCODER_DIG2;
xf86DrvMsg(Output->scrnIndex, X_INFO,
"Mapping DIG2 encoder to %s\n",TransmitterName);
- return TRUE;
} else
return FALSE;
} else
@@ -1635,30 +1633,37 @@ DigAllocFree(struct rhdOutput *Output, enum rhdOutputAllocation Alloc)
atc->Encoder = atomEncoderDIG1;
xf86DrvMsg(Output->scrnIndex, X_INFO,
"Mapping DIG1 encoder to %s\n",TransmitterName);
- return TRUE;
} else if (!rhdPtr->DigEncoderOutput[1]) {
rhdPtr->DigEncoderOutput[1] = Output;
Private->EncoderID = ENCODER_DIG2;
atc->Encoder = atomEncoderDIG2;
xf86DrvMsg(Output->scrnIndex, X_INFO,
"Mapping DIG2 encoder to %s\n",TransmitterName);
- return TRUE;
} else
return FALSE;
}
#else
return FALSE;
#endif
+ if(Private->EncoderMode == TMDS_DVI || Private->EncoderMode == TMDS_HDMI) {
+ Private->Hdmi = RHDHdmiInit(rhdPtr, Output);
+ RHDHdmiSave(Private->Hdmi);
+ RHDHdmiCommitAudioWorkaround(Private->Hdmi);
+ }
+
case RHD_OUTPUT_FREE:
- Private->EncoderID = ENCODER_NONE;
- if (rhdPtr->DigEncoderOutput[0] == Output) {
+ Private->EncoderID = ENCODER_NONE;
+ if (rhdPtr->DigEncoderOutput[0] == Output)
rhdPtr->DigEncoderOutput[0] = NULL;
- return TRUE;
- } else if (rhdPtr->DigEncoderOutput[1] == Output) {
+ else if (rhdPtr->DigEncoderOutput[1] == Output)
rhdPtr->DigEncoderOutput[1] = NULL;
- return TRUE;
- } else
+ else
return FALSE;
+
+ RHDHdmiRestore(Private->Hdmi);
+ RHDHdmiDestroy(Private->Hdmi);
+ Private->Hdmi = NULL;
+ return TRUE;
break;
default:
return FALSE;
@@ -1718,6 +1723,7 @@ RHDDIGInit(RHDPtr rhdPtr, enum rhdOutputType outputType, CARD8 ConnectorType)
Output->Private = Private;
Private->EncoderID = ENCODER_NONE;
+ Private->Hdmi = NULL;
switch (outputType) {
case RHD_OUTPUT_UNIPHYA:
@@ -1880,17 +1886,14 @@ RHDDIGInit(RHDPtr rhdPtr, enum rhdOutputType outputType, CARD8 ConnectorType)
#endif
}
- Private->Hdmi = NULL;
break;
case RHD_CONNECTOR_DVI:
Private->RunDualLink = FALSE; /* will be set later acc to pxclk */
Private->EncoderMode = TMDS_DVI;
- Private->Hdmi = RHDHdmiInit(rhdPtr, Output);
break;
case RHD_CONNECTOR_DVI_SINGLE:
Private->RunDualLink = FALSE;
Private->EncoderMode = TMDS_DVI; /* changed later to HDMI if aplicateable */
- Private->Hdmi = RHDHdmiInit(rhdPtr, Output);
break;
}
diff --git a/src/rhd_hdmi.c b/src/rhd_hdmi.c
index c786fcd..bafbc9d 100644
--- a/src/rhd_hdmi.c
+++ b/src/rhd_hdmi.c
@@ -258,22 +258,39 @@ RHDHdmiInit(RHDPtr rhdPtr, struct rhdOutput* Output)
break;
case RHD_OUTPUT_LVTMA:
- if(RHDOutputTmdsIndex(Output) == 0)
+ switch(RHDOutputTmdsIndex(Output)) {
+ case 0:
hdmi->Offset = HDMI_TMDS;
- else
+ break;
+ case 1:
hdmi->Offset = HDMI_LVTMA;
+ break;
+ default:
+ xfree(hdmi);
+ return NULL;
+ }
break;
case RHD_OUTPUT_UNIPHYA:
- hdmi->Offset = HDMI_TMDS;
- break;
-
+ case RHD_OUTPUT_UNIPHYB:
+ case RHD_OUTPUT_UNIPHYC:
+ case RHD_OUTPUT_UNIPHYD:
+ case RHD_OUTPUT_UNIPHYE:
+ case RHD_OUTPUT_UNIPHYF:
case RHD_OUTPUT_KLDSKP_LVTMA:
- hdmi->Offset = HDMI_DIG;
+ switch(RHDOutputTmdsIndex(Output)) {
+ case 0:
+ hdmi->Offset = HDMI_TMDS;
+ break;
+ case 1:
+ hdmi->Offset = HDMI_DIG;
+ break;
+ default:
+ xfree(hdmi);
+ return NULL;
+ }
break;
- /*case RHD_OUTPUT_UNIPHYB: */
-
default:
xf86DrvMsg(hdmi->scrnIndex, X_ERROR, "%s: unknown HDMI output type\n", __func__);
xfree(hdmi);
@@ -436,6 +453,10 @@ RHDHdmiEnable(struct rhdHdmi *hdmi, Bool Enable)
case RHD_OUTPUT_UNIPHYA:
case RHD_OUTPUT_UNIPHYB:
+ case RHD_OUTPUT_UNIPHYC:
+ case RHD_OUTPUT_UNIPHYD:
+ case RHD_OUTPUT_UNIPHYE:
+ case RHD_OUTPUT_UNIPHYF:
case RHD_OUTPUT_KLDSKP_LVTMA:
/* This part is doubtfull in my opinion */
RHDRegWrite(hdmi, hdmi->Offset+HDMI_ENABLE, Enable ? 0x110 : 0x0);
diff --git a/src/rhd_output.c b/src/rhd_output.c
index 0e33d4e..4a767aa 100644
--- a/src/rhd_output.c
+++ b/src/rhd_output.c
@@ -287,12 +287,12 @@ RHDOutputAttachConnector(struct rhdOutput *Output, struct rhdConnector *Connecto
int
RHDOutputTmdsIndex(struct rhdOutput *Output)
{
- struct rhdOutput *i = RHDPTRI(Output)->Outputs;
+ RHDPtr rhdPtr = RHDPTRI(Output);
+ struct rhdOutput *i = rhdPtr->Outputs;
int index;
switch(Output->Id) {
case RHD_OUTPUT_TMDSA:
- case RHD_OUTPUT_UNIPHYA:
index=0;
break;
@@ -306,9 +306,19 @@ RHDOutputTmdsIndex(struct rhdOutput *Output)
}
break;
+ case RHD_OUTPUT_UNIPHYA:
case RHD_OUTPUT_UNIPHYB:
+ case RHD_OUTPUT_UNIPHYC:
+ case RHD_OUTPUT_UNIPHYD:
+ case RHD_OUTPUT_UNIPHYE:
+ case RHD_OUTPUT_UNIPHYF:
case RHD_OUTPUT_KLDSKP_LVTMA:
- index=1;
+ for(index=0; index<2; index++)
+ if(rhdPtr->DigEncoderOutput[index] == Output)
+ return index;
+
+ xf86DrvMsg(Output->scrnIndex, X_ERROR, "%s: output not assigned to encoder\n", __func__);
+ index=-1;
break;
default:
diff --git a/src/rhd_regs.h b/src/rhd_regs.h
index a233153..ba474df 100644
--- a/src/rhd_regs.h
+++ b/src/rhd_regs.h
@@ -305,6 +305,8 @@ enum {
AUDIO_PIN_WIDGET_CNTL = 0x73d4, /* RO */
AUDIO_STATUS_BITS = 0x73d8, /* RO */
+ R700_AUDIO_UNKNOWN = 0x7604,
+
/* HDMI */
HDMI_TMDS = 0x7400,
HDMI_LVTMA = 0x7700,