xserver-xorg-video-radeonhd: Changes to 'upstream-unstable'
.gitignore | 2
INSTALL | 2
README | 30 +
README.coding | 124 ++++++
acinclude.m4 | 77 ++++
autogen.sh | 4
configure.ac | 30 +
man/radeonhd.man | 128 ++++--
shave-libtool.in | 69 +++
shave.in | 79 ++++
src/Makefile.am | 17
src/atombios_rev.h | 199 ++++++++++
src/r5xx_accel.h | 2
src/r600_exa.c | 14
src/r600_reg.h | 10
src/r600_reg_auto_r6xx.h | 2
src/r600_reg_r6xx.h | 22 -
src/r600_reg_r7xx.h | 64 +--
src/r600_shader.h | 166 ++++----
src/r600_state.h | 4
src/r600_textured_videofuncs.c | 103 +++--
src/r6xx_accel.c | 171 +++------
src/r6xx_accel.h | 12
src/radeon_3d.c | 52 +-
src/radeon_drm.h | 2
src/radeon_exa_render.c | 23 +
src/radeon_textured_videofuncs.c | 4
src/rhd.h | 30 +
src/rhd_acpi.c | 150 ++++++++
src/rhd_acpi.h | 31 +
src/rhd_atombios.c | 731 ++++++++++++++++++++++++++++++++-------
src/rhd_atombios.h | 70 ++-
src/rhd_atomout.c | 75 +++-
src/rhd_audio.c | 52 +-
src/rhd_audio.h | 1
src/rhd_biosscratch.c | 7
src/rhd_connector.c | 2
src/rhd_cs.c | 2
src/rhd_cursor.c | 212 +++++------
src/rhd_cursor.h | 2
src/rhd_dac.c | 4
src/rhd_dig.c | 102 +++--
src/rhd_dri.c | 85 +---
src/rhd_driver.c | 412 ++++++++++++---------
src/rhd_hdmi.c | 146 ++++++-
src/rhd_hdmi.h | 12
src/rhd_i2c.c | 16
src/rhd_id.c | 170 ++++++---
src/rhd_lut.c | 174 +++------
src/rhd_lut.h | 5
src/rhd_lvtma.c | 91 +++-
src/rhd_mc.c | 10
src/rhd_mc.h | 4
src/rhd_monitor.c | 19 -
src/rhd_output.c | 61 +++
src/rhd_output.h | 6
src/rhd_pll.c | 24 -
src/rhd_pm.c | 475 +++++++++++++++++++++++++
src/rhd_pm.h | 78 ++++
src/rhd_randr.c | 183 ++++++++-
src/rhd_regs.h | 79 ++--
src/rhd_tmds.c | 10
src/rhd_video.c | 47 ++
src/rhd_video.h | 9
utils/conntest/Makefile.am | 10
utils/conntest/rhd_conntest.c | 391 +++++++++++++++++++-
utils/conntest/rhd_dump.c | 103 +++++
67 files changed, 4219 insertions(+), 1284 deletions(-)
New commits:
commit 8cbff7bfa1201faa1e5dbf7019f17c2f4b1d2b7f
Author: Matthias Hopf <mhopf@suse.de>
Date: Fri Oct 9 17:42:45 2009 +0200
Bump to 1.3.0. Update README.
diff --git a/README b/README
index 37ae8ab..ddfb2b5 100644
--- a/README
+++ b/README
@@ -92,6 +92,23 @@ Major Changes
Read ChangeLog for a complete list.
+- Version 1.3.0
+
+ - Added support for RV740, M92, M93, M97.
+ - Added support for HDMI audio on RS690 and R700.
+ - Added support for power management.
+ - Implemented almost correct analysis of PowerPlay AtomBIOS tables.
+ - 2D acceleration (EXA) is enabled by default now, except on RV740.
+ - Backlight handling finally fixed - compatible with xbacklight 1.1.1.
+ - Overhaul of memory controller setup. Fixes many "MC not idle" issues.
+ - Overhaul of cursor handling. Fixes most cursor bugs.
+ - Selectable color space for XVideo on R6xx/R7xx.
+ - Tons of bug fixes (DDC, EXA, LUT, RandR, AtomBIOS).
+ - More quirk table entries.
+ - Shave support (cleaner compilation output).
+ - All warnings fixed.
+ - Some start of Developer's documentation in README.coding.
+
- Version 1.2.5
- Added 2D acceleration for R6xx and R7xx.
diff --git a/configure.ac b/configure.ac
index c12da87..3615a9b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
AC_PREREQ(2.57)
AC_INIT([xf86-video-radeonhd],
- 1.2.5,
+ 1.3.0,
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg&component=Driver/radeonhd],
xf86-video-radeonhd)
commit bd2145d8fab854fb5617abd09f7517321d2b35be
Author: Matthias Hopf <mhopf@suse.de>
Date: Fri Oct 9 17:42:30 2009 +0200
pm: Comment out currently unused variable.
diff --git a/src/rhd_pm.c b/src/rhd_pm.c
index 7f3b27c..26433aa 100644
--- a/src/rhd_pm.c
+++ b/src/rhd_pm.c
@@ -66,7 +66,7 @@ rhdPmPrint (struct rhdPm *Pm, char *name, struct rhdPowerState *state)
/* TODO: So far we only know few safe points. Interpolate? */
static void rhdPmValidateSetting (struct rhdPm *Pm, struct rhdPowerState *setting, int forceVoltage)
{
- CARD32 compare = setting->VDDCVoltage ? setting->VDDCVoltage : Pm->Current.VDDCVoltage;
+ /* CARD32 compare = setting->VDDCVoltage ? setting->VDDCVoltage : Pm->Current.VDDCVoltage; */
if (! setting->EngineClock)
setting->EngineClock = Pm->Current.EngineClock;
if (setting->EngineClock < Pm->Minimum.EngineClock)
commit 5c437ecd5d06e1b214d2a309dfed60fadf071829
Author: Matthias Hopf <mhopf@suse.de>
Date: Fri Oct 9 17:31:29 2009 +0200
README.coding: Add rhd_acpi.[ch] and atombios_rev.h
diff --git a/README.coding b/README.coding
index cbc9be2..a2691b2 100644
--- a/README.coding
+++ b/README.coding
@@ -22,6 +22,7 @@ General Stuff
-------------
rhd.h
+rhd_acpi.[ch]
rhd_audio.[ch]
rhd_card.h
rhd_connector.[ch]
@@ -58,6 +59,7 @@ rhd_regs.h
AtomBIOS related
----------------
+atombios_rev.h: Reverse engineered AtomBIOS table definitions
AtomBios/
rhd_atombios.[ch]
rhd_atomcrtc.c
commit 0c8cc053741d7113254776d6c64745ecc5a1256e
Author: Matthias Hopf <mhopf@suse.de>
Date: Fri Oct 9 11:25:06 2009 +0200
i2c: Hardware may need a while to indicate availability to the host
Fixes fdo #24330.
diff --git a/src/rhd_i2c.c b/src/rhd_i2c.c
index dbf00d0..d5b698a 100644
--- a/src/rhd_i2c.c
+++ b/src/rhd_i2c.c
@@ -462,6 +462,7 @@ rhd5xxWriteReadChunk(I2CDevPtr i2cDevPtr, int line, I2CByte *WriteBuffer,
I2CBusPtr I2CPtr = i2cDevPtr->pI2CBus;
rhdI2CPtr I2C = (rhdI2CPtr)(I2CPtr->DriverPrivate.ptr);
int prescale = I2C->prescale;
+ int i;
CARD32 save_I2C_CONTROL1, save_494;
CARD32 tmp32;
Bool ret = TRUE;
@@ -476,8 +477,13 @@ rhd5xxWriteReadChunk(I2CDevPtr i2cDevPtr, int line, I2CByte *WriteBuffer,
R5_DC_I2C_SW_WANTS_TO_USE_I2C,
R5_DC_I2C_SW_WANTS_TO_USE_I2C);
- if (! (RHDRegRead(I2CPtr, R5_DC_I2C_ARBITRATION) & R5_DC_I2C_SW_CAN_USE_I2C)) {
- RHDDebug(I2CPtr->scrnIndex, "%s SW cannot use I2C line %i\n",__func__,line);
+ for (i = 0; i < 50; i++) {
+ if (RHDRegRead(I2CPtr, R5_DC_I2C_ARBITRATION) & R5_DC_I2C_SW_CAN_USE_I2C)
+ break;
+ usleep(1);
+ }
+ if (i >= 50) {
+ xf86DrvMsg(I2CPtr->scrnIndex,X_ERROR, "%s: SW cannot use I2C line %i\n",__func__,line);
ret = FALSE;
} else {
commit 57b97e0fefd7e5a0069573befabdb28ee0094f8d
Author: Matthias Hopf <mhopf@suse.de>
Date: Thu Oct 8 17:10:05 2009 +0200
pm: Improve wording of lowPowerModeEngineClock logging.
diff --git a/src/rhd_pm.c b/src/rhd_pm.c
index f64ba2f..7f3b27c 100644
--- a/src/rhd_pm.c
+++ b/src/rhd_pm.c
@@ -205,7 +205,7 @@ static void rhdPmSelectSettings (RHDPtr rhdPtr)
/* TODO: this should actually set the user mode */
Pm->States[RHD_PM_IDLE].EngineClock = rhdPtr->lowPowerModeEngineClock.val.integer;
xf86DrvMsg(rhdPtr->scrnIndex, X_INFO,
- "ForceLowPowerMode: forced engine clock at %dkHz\n",
+ "ForceLowPowerMode: set idle engine clock to %dkHz\n",
(int) Pm->States[RHD_PM_IDLE].EngineClock);
}
@@ -217,7 +217,7 @@ static void rhdPmSelectSettings (RHDPtr rhdPtr)
} else {
Pm->States[RHD_PM_IDLE].MemoryClock = rhdPtr->lowPowerModeMemoryClock.val.integer;
xf86DrvMsg(rhdPtr->scrnIndex, X_INFO,
- "ForceLowPowerMode: forced memory clock at %dkHz\n",
+ "ForceLowPowerMode: set idle memory clock to %dkHz\n",
(int) Pm->States[RHD_PM_IDLE].MemoryClock);
}
commit a1cd56ddd2955ce74cccc4adcd482feda0985b72
Author: Matthias Hopf <mhopf@suse.de>
Date: Thu Oct 8 16:59:55 2009 +0200
pm: Ignore validation when setting negative engine/mem frequencies.
diff --git a/man/radeonhd.man b/man/radeonhd.man
index e1e8e84..7a1641a 100644
--- a/man/radeonhd.man
+++ b/man/radeonhd.man
@@ -496,7 +496,8 @@ can help reduce power consumption. The default is
.TP
.BI "Option \*qLowPowerModeEngineClock\*q \*q" integer \*q
Engine clock frequency to use when ForceLowPowerMode is enabled, in Hz. If not
-set, the minimum known working frequency is used.
+set, the minimum known working frequency is used. If integer is negative,
+validation is skipped, and the absolute value is used for the engine clock.
.\"
.\"
.SH RANDR OUTPUT PROPERTIES
diff --git a/src/rhd_pm.c b/src/rhd_pm.c
index 0d467b3..f64ba2f 100644
--- a/src/rhd_pm.c
+++ b/src/rhd_pm.c
@@ -222,6 +222,17 @@ static void rhdPmSelectSettings (RHDPtr rhdPtr)
}
rhdPmValidateSetting (Pm, &Pm->States[RHD_PM_IDLE], 1);
+
+ if (rhdPtr->lowPowerModeEngineClock.val.integer < 0) {
+ Pm->States[RHD_PM_IDLE].EngineClock = - rhdPtr->lowPowerModeEngineClock.val.integer;
+ xf86DrvMsg(rhdPtr->scrnIndex, X_WARNING,
+ "ForceLowPowerMode: user requested to ignore validation for engine clock\n");
+ }
+ if (rhdPtr->lowPowerModeMemoryClock.val.integer < 0) {
+ Pm->States[RHD_PM_IDLE].MemoryClock = - rhdPtr->lowPowerModeMemoryClock.val.integer;
+ xf86DrvMsg(rhdPtr->scrnIndex, X_WARNING,
+ "ForceLowPowerMode: user requested to ignore validation for memory clock\n");
+ }
}
memcpy (&Pm->States[RHD_PM_MAX_3D], &Pm->Maximum, sizeof (struct rhdPowerState));
commit 5d5d8e3d8655a7adbc17a548372bc0fad6d67cb7
Author: Matthias Hopf <mhopf@suse.de>
Date: Thu Oct 8 16:57:21 2009 +0200
pm: Use minimum known working frequency instead of default/2.
diff --git a/man/radeonhd.man b/man/radeonhd.man
index 3d3a508..e1e8e84 100644
--- a/man/radeonhd.man
+++ b/man/radeonhd.man
@@ -496,7 +496,7 @@ can help reduce power consumption. The default is
.TP
.BI "Option \*qLowPowerModeEngineClock\*q \*q" integer \*q
Engine clock frequency to use when ForceLowPowerMode is enabled, in Hz. If not
-set, half of default clock frequency is used.
+set, the minimum known working frequency is used.
.\"
.\"
.SH RANDR OUTPUT PROPERTIES
diff --git a/src/rhd_pm.c b/src/rhd_pm.c
index f67af05..0d467b3 100644
--- a/src/rhd_pm.c
+++ b/src/rhd_pm.c
@@ -195,13 +195,12 @@ static void rhdPmSelectSettings (RHDPtr rhdPtr)
memcpy (&Pm->States[RHD_PM_OFF], &Pm->Minimum, sizeof (struct rhdPowerState));
if (rhdPtr->lowPowerMode.val.bool) {
- /* Idle: !!!HACK!!! Take half the default */
/* TODO: copy lowest config with default Voltage/Mem setting? */
if (!rhdPtr->lowPowerModeEngineClock.val.integer) {
- Pm->States[RHD_PM_IDLE].EngineClock = Pm->Default.EngineClock / 2;
- xf86DrvMsg(rhdPtr->scrnIndex, X_INFO,
- "ForceLowPowerMode: calculated engine clock at %dkHz\n",
- (int) Pm->States[RHD_PM_IDLE].EngineClock);
+ Pm->States[RHD_PM_IDLE].EngineClock = Pm->States[RHD_PM_OFF].EngineClock;
+ xf86DrvMsg(rhdPtr->scrnIndex, X_INFO,
+ "ForceLowPowerMode: calculated engine clock at %dkHz\n",
+ (int) Pm->States[RHD_PM_IDLE].EngineClock);
} else {
/* TODO: this should actually set the user mode */
Pm->States[RHD_PM_IDLE].EngineClock = rhdPtr->lowPowerModeEngineClock.val.integer;
@@ -211,7 +210,7 @@ static void rhdPmSelectSettings (RHDPtr rhdPtr)
}
if (!rhdPtr->lowPowerModeMemoryClock.val.integer) {
- Pm->States[RHD_PM_IDLE].MemoryClock = Pm->Default.MemoryClock / 2;
+ Pm->States[RHD_PM_IDLE].MemoryClock = Pm->States[RHD_PM_OFF].MemoryClock;
xf86DrvMsg(rhdPtr->scrnIndex, X_INFO,
"ForceLowPowerMode: calculated memory clock at %dkHz\n",
(int) Pm->States[RHD_PM_IDLE].MemoryClock);
commit 0a94f8eb56ec0155864858f8aefc4c64d3e1bf77
Author: Matthias Hopf <mhopf@suse.de>
Date: Thu Oct 8 16:02:46 2009 +0200
pm: Do NOT set idle engine clocks to default/2 unless ForceLowPowerMode is used.
Accidentally, we set this by default since commit fedddb7.
Using different engine clocks has side effects that are not handled yet.
diff --git a/src/rhd_pm.c b/src/rhd_pm.c
index 9efa1b0..f67af05 100644
--- a/src/rhd_pm.c
+++ b/src/rhd_pm.c
@@ -194,17 +194,16 @@ static void rhdPmSelectSettings (RHDPtr rhdPtr)
/* RHD_PM_OFF: minimum */
memcpy (&Pm->States[RHD_PM_OFF], &Pm->Minimum, sizeof (struct rhdPowerState));
- /* Idle: !!!HACK!!! Take half the default */
- /* TODO: copy lowest config with default Voltage/Mem setting? */
- /* TODO: this should actually set the user mode */
- Pm->States[RHD_PM_IDLE].EngineClock = Pm->Default.EngineClock / 2;
if (rhdPtr->lowPowerMode.val.bool) {
+ /* Idle: !!!HACK!!! Take half the default */
+ /* TODO: copy lowest config with default Voltage/Mem setting? */
if (!rhdPtr->lowPowerModeEngineClock.val.integer) {
Pm->States[RHD_PM_IDLE].EngineClock = Pm->Default.EngineClock / 2;
xf86DrvMsg(rhdPtr->scrnIndex, X_INFO,
"ForceLowPowerMode: calculated engine clock at %dkHz\n",
(int) Pm->States[RHD_PM_IDLE].EngineClock);
} else {
+ /* TODO: this should actually set the user mode */
Pm->States[RHD_PM_IDLE].EngineClock = rhdPtr->lowPowerModeEngineClock.val.integer;
xf86DrvMsg(rhdPtr->scrnIndex, X_INFO,
"ForceLowPowerMode: forced engine clock at %dkHz\n",
commit eebdbf0a9723c79975015354830550f7dfb57509
Author: Egbert Eich <eich@freedesktop.org>
Date: Thu Oct 8 09:15:32 2009 +0200
Improve DAC load detection on RS780.
Increase delay before reading out DAC autodetect status.
diff --git a/src/rhd_dac.c b/src/rhd_dac.c
index bfed38c..8d05fe5 100644
--- a/src/rhd_dac.c
+++ b/src/rhd_dac.c
@@ -648,7 +648,7 @@ DACSenseRV620(struct rhdOutput *Output, CARD32 offset, Bool TV)
/* enable comparators for R/G/B, disable DDET and SDET reference */
RHDRegMask(Output, offset + RV620_DACA_COMPARATOR_ENABLE, 0x70000, 0x070101);
RHDRegMask(Output, offset + RV620_DACA_AUTODETECT_CONTROL, 0x01, 0xff);
- usleep(32);
+ usleep(50);
ret = RHDRegRead(Output, offset + RV620_DACA_AUTODETECT_STATUS);
RHDRegWrite(Output, offset + RV620_DACA_AUTODETECT_CONTROL, DetectControl);
RHDRegWrite(Output, offset + RV620_DACA_MACRO_CNTL, Control1);
diff --git a/utils/conntest/rhd_conntest.c b/utils/conntest/rhd_conntest.c
index c7ecd41..f1db552 100644
--- a/utils/conntest/rhd_conntest.c
+++ b/utils/conntest/rhd_conntest.c
@@ -898,10 +898,10 @@ RV620DACLoadDetect(void *map, Bool tv, int dac)
RegMask(map, offset + RV620_DACA_CONTROL2, 0x1, 0x1);
/* enable r/g/b comparators, disable D/SDET ref */
RegMask(map, offset + RV620_DACA_COMPARATOR_ENABLE, 0x70000, 0x070101);
- usleep(100);
+ //usleep(100);
/* check for connection */
RegMask(map, offset + RV620_DACA_AUTODETECT_CONTROL, 0x01, 0xff);
- usleep(32);
+ usleep(50);
ret = RegRead(map, offset + RV620_DACA_AUTODETECT_STATUS);
commit 422ac06b69cfcbfbaa802fdc916d3b87f40eeb41
Author: Christian König <deathsimple@vodafone.de>
Date: Thu Oct 8 00:04:01 2009 +0200
Silence audio stream option.
This patch adds an option to play silence instead of playing no sound at all.
This fixes some issues where a receiver needs 1-2 seconds to adjust to a new audio stream.
This option can be enabled by setting AudioStreamSilence in xorg.conf or by xrandr.
diff --git a/src/rhd.h b/src/rhd.h
index 43adb30..efa6bc2 100644
--- a/src/rhd.h
+++ b/src/rhd.h
@@ -247,6 +247,7 @@ typedef struct RHDRec {
RHDOpt scaleTypeOpt;
RHDOpt unverifiedFeatures;
RHDOpt audio;
+ RHDOpt audioWorkaround;
RHDOpt hdmi;
RHDOpt coherent;
RHDOpt lowPowerMode;
diff --git a/src/rhd_atomout.c b/src/rhd_atomout.c
index b88b1bd..9d50ade 100644
--- a/src/rhd_atomout.c
+++ b/src/rhd_atomout.c
@@ -745,6 +745,7 @@ atomTMDSPropertyControl(struct rhdOutput *Output,
switch (Property) {
case RHD_OUTPUT_COHERENT:
case RHD_OUTPUT_HDMI:
+ case RHD_OUTPUT_AUDIO_WORKAROUND:
return TRUE;
default:
return FALSE;
@@ -757,6 +758,9 @@ atomTMDSPropertyControl(struct rhdOutput *Output,
case RHD_OUTPUT_HDMI:
val->Bool = atomIsHdmiEnabled(Output);
return TRUE;
+ case RHD_OUTPUT_AUDIO_WORKAROUND:
+ val->Bool = RHDHdmiGetAudioWorkaround(Private->Hdmi);
+ return TRUE;
default:
return FALSE;
}
@@ -769,6 +773,9 @@ atomTMDSPropertyControl(struct rhdOutput *Output,
case RHD_OUTPUT_HDMI:
atomSetHdmiEnabled(Output, val->Bool);
break;
+ case RHD_OUTPUT_AUDIO_WORKAROUND:
+ RHDHdmiSetAudioWorkaround(Private->Hdmi, val->Bool);
+ break;
default:
return FALSE;
}
@@ -780,6 +787,9 @@ atomTMDSPropertyControl(struct rhdOutput *Output,
Output->Mode(Output, Private->Mode);
Output->Power(Output, RHD_POWER_ON);
break;
+ case RHD_OUTPUT_AUDIO_WORKAROUND:
+ RHDHdmiCommitAudioWorkaround(Private->Hdmi);
+ break;
default:
return FALSE;
}
diff --git a/src/rhd_audio.c b/src/rhd_audio.c
index de5f5ce..5e3c4e2 100644
--- a/src/rhd_audio.c
+++ b/src/rhd_audio.c
@@ -90,14 +90,16 @@ AudioRate(struct rhdAudio* Audio)
return result;
}
+#if 0
/*
- * something playing ?
+ * something playing ? (not used anymore)
*/
static Bool
AudioPlaying(struct rhdAudio* Audio)
{
return (RHDRegRead(Audio, AUDIO_PLAYING) >> 4) & 1;
}
+#endif
/*
* iec 60958 status bits
@@ -124,35 +126,36 @@ static CARD32
AudioUpdateHdmi(OsTimerPtr timer, CARD32 time, pointer ptr)
{
struct rhdAudio *Audio = (struct rhdAudio*)ptr;
- Bool playing = AudioPlaying(Audio);
int channels = AudioChannels(Audio);
int rate = AudioRate(Audio);
int bps = AudioBitsPerSample(Audio);
CARD8 status_bits = AudioStatusBits(Audio);
CARD8 category_code = AudioCategoryCode(Audio);
+ Bool changes = FALSE;
+
struct rhdHdmi* hdmi;
- if(playing != Audio->SavedPlaying ||
- channels != Audio->SavedChannels ||
- rate != Audio->SavedRate ||
- bps != Audio->SavedBitsPerSample ||
- status_bits != Audio->SavedStatusBits ||
- category_code != Audio->SavedCategoryCode) {
+ changes |= channels != Audio->SavedChannels;
+ changes |= rate != Audio->SavedRate;
+ changes |= bps != Audio->SavedBitsPerSample;
+ changes |= status_bits != Audio->SavedStatusBits;
+ changes |= category_code != Audio->SavedCategoryCode;
- Audio->SavedPlaying = playing;
+ if(changes) {
Audio->SavedChannels = channels;
Audio->SavedRate = rate;
Audio->SavedBitsPerSample = bps;
Audio->SavedStatusBits = status_bits;
Audio->SavedCategoryCode = category_code;
+ }
- for(hdmi=Audio->Registered; hdmi != NULL; hdmi=hdmi->Next)
+ for(hdmi=Audio->Registered; hdmi != NULL; hdmi=hdmi->Next)
+ if(changes || RHDHdmiBufferStatusChanged(hdmi))
RHDHdmiUpdateAudioSettings(
- hdmi, playing, channels,
+ hdmi, channels,
rate, bps, status_bits,
category_code);
- }
return AUDIO_TIMER_INTERVALL;
}
@@ -303,6 +306,9 @@ RHDAudioRegisterHdmi(RHDPtr rhdPtr, struct rhdHdmi* rhdHdmi)
if(!rhdHdmi)
return;
+ /* make shure the HDMI interface is not registered */
+ RHDAudioUnregisterHdmi(rhdPtr, rhdHdmi);
+
rhdHdmi->Next = Audio->Registered;
Audio->Registered = rhdHdmi;
}
@@ -318,7 +324,7 @@ void RHDAudioUnregisterHdmi(RHDPtr rhdPtr, struct rhdHdmi* rhdHdmi)
if (!Audio) return;
RHDFUNC(Audio);
- for(hdmiPtr=&Audio->Registered; hdmiPtr!=NULL;hdmiPtr=&(*hdmiPtr)->Next)
+ for(hdmiPtr=&Audio->Registered; *hdmiPtr!=NULL;hdmiPtr=&(*hdmiPtr)->Next)
if(*hdmiPtr == rhdHdmi) {
*hdmiPtr = rhdHdmi->Next;
rhdHdmi->Next = NULL;
diff --git a/src/rhd_audio.h b/src/rhd_audio.h
index d74016c..82932e9 100644
--- a/src/rhd_audio.h
+++ b/src/rhd_audio.h
@@ -34,7 +34,6 @@ struct rhdAudio {
struct rhdHdmi* Registered;
OsTimerPtr Timer;
- Bool SavedPlaying;
int SavedChannels;
int SavedRate;
int SavedBitsPerSample;
diff --git a/src/rhd_dig.c b/src/rhd_dig.c
index 6e75fd0..782c8db 100644
--- a/src/rhd_dig.c
+++ b/src/rhd_dig.c
@@ -262,6 +262,7 @@ TMDSTransmitterPropertyControl(struct rhdOutput *Output,
switch (Property) {
case RHD_OUTPUT_COHERENT:
case RHD_OUTPUT_HDMI:
+ case RHD_OUTPUT_AUDIO_WORKAROUND:
return TRUE;
default:
return FALSE;
@@ -274,6 +275,9 @@ TMDSTransmitterPropertyControl(struct rhdOutput *Output,
case RHD_OUTPUT_HDMI:
val->Bool = Private->EncoderMode == TMDS_HDMI;
return TRUE;
+ case RHD_OUTPUT_AUDIO_WORKAROUND:
+ val->Bool = RHDHdmiGetAudioWorkaround(Private->Hdmi);
+ return TRUE;
default:
return FALSE;
}
@@ -286,6 +290,9 @@ TMDSTransmitterPropertyControl(struct rhdOutput *Output,
case RHD_OUTPUT_HDMI:
Private->EncoderMode = val->Bool ? TMDS_HDMI : TMDS_DVI;
break;
+ case RHD_OUTPUT_AUDIO_WORKAROUND:
+ RHDHdmiSetAudioWorkaround(Private->Hdmi, val->Bool);
+ break;
default:
return FALSE;
}
@@ -297,6 +304,9 @@ TMDSTransmitterPropertyControl(struct rhdOutput *Output,
Output->Mode(Output, Private->Mode);
Output->Power(Output, RHD_POWER_ON);
break;
+ case RHD_OUTPUT_AUDIO_WORKAROUND:
+ RHDHdmiCommitAudioWorkaround(Private->Hdmi);
+ break;
default:
return FALSE;
}
@@ -1472,6 +1482,7 @@ DigPropertyControl(struct rhdOutput *Output,
case RHD_OUTPUT_COHERENT:
case RHD_OUTPUT_BACKLIGHT:
case RHD_OUTPUT_HDMI:
+ case RHD_OUTPUT_AUDIO_WORKAROUND:
{
if (!Private->Transmitter.Property)
return FALSE;
diff --git a/src/rhd_driver.c b/src/rhd_driver.c
index 649cadb..e502c5f 100644
--- a/src/rhd_driver.c
+++ b/src/rhd_driver.c
@@ -261,6 +261,7 @@ typedef enum {
#endif
OPTION_UNVERIFIED_FEAT,
OPTION_AUDIO,
+ OPTION_AUDIO_WORKAROUND,
OPTION_HDMI,
OPTION_COHERENT,
OPTION_FORCE_LOW_POWER,
@@ -292,6 +293,7 @@ static const OptionInfoRec RHDOptions[] = {
#endif
{ OPTION_UNVERIFIED_FEAT, "UnverifiedFeatures", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_AUDIO, "Audio", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_AUDIO_WORKAROUND, "AudioStreamSilence", OPTV_ANYSTR, {0}, FALSE },
{ OPTION_HDMI, "HDMI", OPTV_ANYSTR, {0}, FALSE },
{ OPTION_COHERENT, "COHERENT", OPTV_ANYSTR, {0}, FALSE },
{ OPTION_FORCE_LOW_POWER, "ForceLowPowerMode", OPTV_BOOLEAN, {0}, FALSE },
@@ -2844,6 +2846,8 @@ rhdProcessOptions(ScrnInfoPtr pScrn)
&rhdPtr->unverifiedFeatures, FALSE);
RhdGetOptValBool (rhdPtr->Options, OPTION_AUDIO,
&rhdPtr->audio, TRUE);
+ RhdGetOptValString (rhdPtr->Options, OPTION_AUDIO_WORKAROUND,
+ &rhdPtr->audioWorkaround, "none");
RhdGetOptValString (rhdPtr->Options, OPTION_HDMI,
&rhdPtr->hdmi, "none");
RhdGetOptValString(rhdPtr->Options, OPTION_COHERENT,
diff --git a/src/rhd_hdmi.c b/src/rhd_hdmi.c
index 62ab861..c786fcd 100644
--- a/src/rhd_hdmi.c
+++ b/src/rhd_hdmi.c
@@ -229,26 +229,16 @@ HdmiAudioInfoFrame(
}
/*
- * it's unknown what these bits do excatly, but it's indeed quite usefull for debugging
+ * test if audio buffer is filled enough to start playing
*/
-static void
-HdmiAudioDebugWorkaround(struct rhdHdmi* hdmi, Bool Enable)
+static Bool
+IsAudioBufferFilled(struct rhdHdmi *hdmi)
{
- 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);
- } else {
- RHDRegMask(hdmi, hdmi->Offset+HDMI_CNTL, 0, 0x1000);
- }
+ return (RHDRegRead(hdmi, hdmi->Offset+HDMI_STATUS) & 0x10) != 0;
}
/*
* allocate/initialize the HDMI structure
- * and register with audio engine
* output selects which engine is used
*/
struct rhdHdmi*
@@ -291,7 +281,6 @@ RHDHdmiInit(RHDPtr rhdPtr, struct rhdOutput* Output)
break;
}
hdmi->Stored = FALSE;
- RHDAudioRegisterHdmi(rhdPtr, hdmi);
return hdmi;
} else
return NULL;
@@ -308,8 +297,6 @@ RHDHdmiSetMode(struct rhdHdmi *hdmi, DisplayModePtr Mode)
RHDAudioSetClock(RHDPTRI(hdmi), hdmi->Output, Mode->Clock);
- HdmiAudioDebugWorkaround(hdmi, FALSE);
-
RHDRegWrite(hdmi, hdmi->Offset+HDMI_UNKNOWN_0, 0x1000);
RHDRegWrite(hdmi, hdmi->Offset+HDMI_UNKNOWN_1, 0x0);
RHDRegWrite(hdmi, hdmi->Offset+HDMI_UNKNOWN_2, 0x1000);
@@ -323,20 +310,45 @@ RHDHdmiSetMode(struct rhdHdmi *hdmi, DisplayModePtr Mode)
HdmiVideoInfoFrame(hdmi, RGB, FALSE, 0, 0, 0,
0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ /* it's unknown what these bits do excatly, but it's indeed quite usefull for debugging */
+ 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);
+
+ RHDHdmiCommitAudioWorkaround(hdmi);
+
/* audio packets per line, does anyone know how to calc this ? */
- RHDRegMask(hdmi, hdmi->Offset+HDMI_CNTL, 0x020000, 0x1F0000);
+ RHDRegMask(hdmi, hdmi->Offset+HDMI_CNTL, 0x00040000, 0x001F0000);
/* update? reset? don't realy know */
RHDRegMask(hdmi, hdmi->Offset+HDMI_CNTL, 0x14000000, 0x14000000);
}
/*
+ * have buffer status changed since last call?
+ */
+Bool
+RHDHdmiBufferStatusChanged(struct rhdHdmi* hdmi)
+{
+ Bool status, result;
+
+ if(!hdmi) return FALSE;
+ RHDFUNC(hdmi);
+
+ status = IsAudioBufferFilled(hdmi);
+ result = hdmi->SavedBufferStatus != status;
+ hdmi->SavedBufferStatus = status;
+
+ return result;
+}
+
+/*
* update settings with current parameters from audio engine
*/
void
RHDHdmiUpdateAudioSettings(
struct rhdHdmi* hdmi,
- Bool playing,
int channels,
int rate,
int bps,
@@ -351,13 +363,11 @@ RHDHdmiUpdateAudioSettings(
xf86DrvMsg(hdmi->scrnIndex, X_INFO, "%s: %s with "
"%d channels, %d Hz sampling rate, %d bits per sample,\n",
- __func__, playing ? "playing" : "stopped", channels, rate, bps);
+ __func__, IsAudioBufferFilled(hdmi) ? "playing" : "stopped",
+ channels, rate, bps);
xf86DrvMsg(hdmi->scrnIndex, X_INFO, "%s: "
"0x%02x IEC60958 status bits and 0x%02x category code\n",
- __func__, (int)status_bits, (int)category_code);
-
- /* start delivering audio frames */
- RHDRegMask(hdmi, hdmi->Offset+HDMI_CNTL, playing ? 1 : 0, 0x1);
+ __func__, (int)status_bits, (int)category_code);
iec = 0;
if(status_bits & AUDIO_STATUS_PROFESSIONAL) iec |= 1 << 0;
@@ -395,12 +405,15 @@ RHDHdmiUpdateAudioSettings(
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);
+ RHDHdmiCommitAudioWorkaround(hdmi);
+
+ /* update? reset? don't realy know */
+ RHDRegMask(hdmi, hdmi->Offset+HDMI_CNTL, 0x04000000, 0x04000000);
}
/*
* enable/disable the HDMI engine
+ * and register with audio engine
*/
void
RHDHdmiEnable(struct rhdHdmi *hdmi, Bool Enable)
@@ -432,6 +445,57 @@ RHDHdmiEnable(struct rhdHdmi *hdmi, Bool Enable)
xf86DrvMsg(hdmi->scrnIndex, X_ERROR, "%s: unknown HDMI output type\n", __func__);
break;
}
+ if(Enable)
+ RHDAudioRegisterHdmi(RHDPTRI(hdmi), hdmi);
+ else
+ RHDAudioUnregisterHdmi(RHDPTRI(hdmi), hdmi);
+}
+
+/*
+ * enable/disable the audio workaround function
+ */
+void
+RHDHdmiSetAudioWorkaround(struct rhdHdmi* hdmi, Bool Enable)
+{
+ if(!hdmi) return;
+ RHDFUNC(hdmi);
+
+ hdmi->AudioDebugWorkaround = Enable;
+}
+
+/*
+ * get status of the audio workaround function
+ */
+Bool
+RHDHdmiGetAudioWorkaround(struct rhdHdmi* hdmi)
+{
+ if(!hdmi) return FALSE;
+ RHDFUNC(hdmi);
+
+ return hdmi->AudioDebugWorkaround;
+}
+
+/*
+ * commit the audio workaround status to the hardware
+ */
+void
+RHDHdmiCommitAudioWorkaround(struct rhdHdmi* hdmi)
+{
+ if(!hdmi) return;
+ RHDFUNC(hdmi);
+
+ if(IsAudioBufferFilled(hdmi)) {
+ /* disable audio workaround and start delivering of audio frames */
+ RHDRegMask(hdmi, hdmi->Offset+HDMI_CNTL, 0x00000001, 0x00001001);
+
+ } else if(hdmi->AudioDebugWorkaround) {
+ /* enable audio workaround and start delivering of audio frames */
+ RHDRegMask(hdmi, hdmi->Offset+HDMI_CNTL, 0x00001001, 0x00001001);
+
+ } else {
+ /* disable audio workaround and stop delivering of audio frames */
+ RHDRegMask(hdmi, hdmi->Offset+HDMI_CNTL, 0x00000000, 0x00001001);
+ }
}
/*
diff --git a/src/rhd_hdmi.h b/src/rhd_hdmi.h
index 5b1e8f0..e86b5e2 100644
--- a/src/rhd_hdmi.h
+++ b/src/rhd_hdmi.h
@@ -35,6 +35,9 @@ struct rhdHdmi {
struct rhdOutput* Output;
CARD16 Offset;
+ Bool SavedBufferStatus;
+ Bool AudioDebugWorkaround;
+
Bool Stored;
CARD32 StoreEnable;
CARD32 StoreControl;
@@ -63,9 +66,10 @@ struct rhdHdmi* RHDHdmiInit(RHDPtr rhdPtr, struct rhdOutput* Output);
void RHDHdmiSetMode(struct rhdHdmi* rhdHdmi, DisplayModePtr Mode);
void RHDHdmiEnable(struct rhdHdmi* rhdHdmi, Bool Enable);
+
+Bool RHDHdmiBufferStatusChanged(struct rhdHdmi* hdmi);
void RHDHdmiUpdateAudioSettings(
struct rhdHdmi* rhdHdmi,
- Bool playing,
int channels,
int rate,
int bps,
@@ -73,6 +77,10 @@ void RHDHdmiUpdateAudioSettings(
CARD8 catgory_code
);
+void RHDHdmiSetAudioWorkaround(struct rhdHdmi* rhdHdmi, Bool Enabled);
+Bool RHDHdmiGetAudioWorkaround(struct rhdHdmi* rhdHdmi);
+void RHDHdmiCommitAudioWorkaround(struct rhdHdmi* rhdHdmi);
+
void RHDHdmiSave(struct rhdHdmi* rhdHdmi);
void RHDHdmiRestore(struct rhdHdmi* rhdHdmi);
diff --git a/src/rhd_lvtma.c b/src/rhd_lvtma.c
index 685aef6..a4aeb9e 100644
--- a/src/rhd_lvtma.c
+++ b/src/rhd_lvtma.c
@@ -1069,6 +1069,7 @@ TMDSBPropertyControl(struct rhdOutput *Output,
switch (Property) {
case RHD_OUTPUT_COHERENT:
case RHD_OUTPUT_HDMI:
+ case RHD_OUTPUT_AUDIO_WORKAROUND:
return TRUE;
default:
return FALSE;
@@ -1081,6 +1082,9 @@ TMDSBPropertyControl(struct rhdOutput *Output,
case RHD_OUTPUT_HDMI:
val->Bool = Private->HdmiEnabled;
return TRUE;
+ case RHD_OUTPUT_AUDIO_WORKAROUND:
+ val->Bool = RHDHdmiGetAudioWorkaround(Private->Hdmi);
+ return TRUE;
default:
return FALSE;
}
@@ -1093,6 +1097,9 @@ TMDSBPropertyControl(struct rhdOutput *Output,
case RHD_OUTPUT_HDMI:
Private->HdmiEnabled = val->Bool;
break;
+ case RHD_OUTPUT_AUDIO_WORKAROUND:
+ RHDHdmiSetAudioWorkaround(Private->Hdmi, val->Bool);
+ break;
default:
return FALSE;
}
@@ -1104,6 +1111,9 @@ TMDSBPropertyControl(struct rhdOutput *Output,
Output->Mode(Output, Private->Mode);
Output->Power(Output, RHD_POWER_ON);
break;
+ case RHD_OUTPUT_AUDIO_WORKAROUND:
+ RHDHdmiCommitAudioWorkaround(Private->Hdmi);
+ break;
default:
return FALSE;
}
diff --git a/src/rhd_output.c b/src/rhd_output.c
index 2219582..0e33d4e 100644
--- a/src/rhd_output.c
+++ b/src/rhd_output.c
@@ -260,6 +260,25 @@ RHDOutputAttachConnector(struct rhdOutput *Output, struct rhdConnector *Connecto
if(!Output->Property(Output, rhdPropertySet, RHD_OUTPUT_HDMI, &val))
xf86DrvMsg(rhdPtr->scrnIndex, X_WARNING, "Failed to %s HDMI on %s\n", val.Bool ? "disable" : "enable", Output->Name);
}
+
+ /* check config option if we should enable audio workaround */
+ if (Output->Property(Output, rhdPropertyCheck, RHD_OUTPUT_AUDIO_WORKAROUND, NULL)) {
+ union rhdPropertyData val;
+ switch(RhdParseBooleanOption(&rhdPtr->audioWorkaround, Connector->Name)) {
+ case RHD_OPTION_NOT_SET:
+ case RHD_OPTION_OFF:
+ val.Bool = FALSE;
+ break;
+ case RHD_OPTION_ON:
+ case RHD_OPTION_DEFAULT:
+ val.Bool = TRUE;
+ break;
+ }
+ if(!Output->Property(Output, rhdPropertySet, RHD_OUTPUT_AUDIO_WORKAROUND, &val))
+ xf86DrvMsg(rhdPtr->scrnIndex, X_WARNING,
+ "Failed to %s audio workaorund on %s\n",
+ val.Bool ? "disable" : "enable", Output->Name);
+ }
}
/*
diff --git a/src/rhd_output.h b/src/rhd_output.h
index 0e7b6a2..4862478 100644
--- a/src/rhd_output.h
+++ b/src/rhd_output.h
@@ -59,7 +59,8 @@ typedef enum rhdSensedOutput {
enum rhdOutputProperty {
RHD_OUTPUT_BACKLIGHT,
RHD_OUTPUT_COHERENT,
- RHD_OUTPUT_HDMI
+ RHD_OUTPUT_HDMI,
+ RHD_OUTPUT_AUDIO_WORKAROUND
};
enum rhdOutputAllocation {
diff --git a/src/rhd_randr.c b/src/rhd_randr.c
index 568c0cd..956119b 100644
--- a/src/rhd_randr.c
+++ b/src/rhd_randr.c
@@ -130,11 +130,12 @@ struct rhdRandrCrtc {
#define ATOM_BACKLIGHT "Backlight"
#define ATOM_COHERENT "_Coherent"
#define ATOM_HDMI "_HDMI"
+#define ATOM_AUDIO_WORKAROUND "_AudioStreamSilence"
#define ATOM_ATOMBIOS "_AtomBIOS"
static Atom atom_SignalFormat, atom_ConnectorType, atom_ConnectorNumber,
atom_OutputNumber, atom_PanningArea, atom_Backlight, atom_Coherent,
- atom_HdmiProperty;
+ atom_HdmiProperty, atom_AudioWorkaround;
static Atom atom_unknown, atom_VGA, atom_TMDS, atom_LVDS, atom_DisplayPort, atom_TV;
static Atom atom_DVI, atom_DVII, atom_DVID, atom_DVIA, atom_HDMI, atom_Panel;
static Atom atom_EDID, atom_EDID2, atom_AtomBIOS;
@@ -713,6 +714,30 @@ rhdRROutputCreateResources(xf86OutputPtr out)
__func__, err);
}
}
+ if (rout->Output->Property(rout->Output, rhdPropertyCheck, RHD_OUTPUT_AUDIO_WORKAROUND, NULL)) {
+ atom_AudioWorkaround = MakeAtom(ATOM_AUDIO_WORKAROUND, sizeof(ATOM_AUDIO_WORKAROUND)-1, TRUE);
+
+ range[0] = 0;
+ range[1] = 1;
+ err = RRConfigureOutputProperty(out->randr_output, atom_AudioWorkaround,
+ FALSE, TRUE, FALSE, 2, range);
+ if (err != 0)
+ xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR,
+ "RRConfigureOutputProperty error: %d\n", err);
+ else {
+ union rhdPropertyData val;
+
+ if (!rout->Output->Property(rout->Output, rhdPropertyGet, RHD_OUTPUT_AUDIO_WORKAROUND, &val))
+ val.Bool = 1;
+ err = RRChangeOutputProperty(out->randr_output, atom_AudioWorkaround,
+ XA_INTEGER, 32, PropModeReplace,
+ 1, &val.Bool, FALSE, FALSE);
+ if (err != 0)
Reply to: