[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: