.gitignore | 2 INSTALL | 2 Makefile.am | 2 README | 44 README.coding | 124 + acinclude.m4 | 77 autogen.sh | 4 configure.ac | 31 man/radeonhd.man | 238 +-- shave-libtool.in | 69 shave.in | 79 src/Makefile.am | 26 src/atombios_rev.h | 199 ++ src/r5xx_accel.c | 9 src/r5xx_accel.h | 4 src/r5xx_exa.c | 12 src/r5xx_xaa.c | 2 src/r600_exa.c | 2164 +++++++++++++++++++++++++++ src/r600_reg.h | 132 + src/r600_reg_auto_r6xx.h | 3087 +++++++++++++++++++++++++++++++++++++++ src/r600_reg_r6xx.h | 504 ++++++ src/r600_reg_r7xx.h | 149 + src/r600_shader.c | 1848 +++++++++++++++++++++++ src/r600_shader.h | 359 ++++ src/r600_state.h | 293 +++ src/r600_textured_videofuncs.c | 558 +++++++ src/r6xx_accel.c | 1202 +++++++++++++++ src/r6xx_accel.h | 89 + src/radeon_3d.c | 52 src/radeon_drm.h | 2 src/radeon_exa_render.c | 25 src/radeon_textured_videofuncs.c | 4 src/rhd.h | 77 src/rhd_acpi.c | 150 + src/rhd_acpi.h | 31 src/rhd_atombios.c | 735 +++++++-- src/rhd_atombios.h | 72 src/rhd_atomcrtc.c | 15 src/rhd_atomout.c | 217 +- src/rhd_atomout.h | 2 src/rhd_atompll.c | 2 src/rhd_atomwrapper.c | 2 src/rhd_atomwrapper.h | 2 src/rhd_audio.c | 56 src/rhd_audio.h | 3 src/rhd_biosscratch.c | 9 src/rhd_biosscratch.h | 2 src/rhd_card.h | 2 src/rhd_connector.c | 4 src/rhd_connector.h | 2 src/rhd_crtc.c | 47 src/rhd_crtc.h | 4 src/rhd_cs.c | 29 src/rhd_cs.h | 2 src/rhd_cursor.c | 206 +- src/rhd_cursor.h | 4 src/rhd_dac.c | 6 src/rhd_ddia.c | 2 src/rhd_dig.c | 302 ++- src/rhd_dri.c | 228 +- src/rhd_dri.h | 2 src/rhd_driver.c | 609 ++++--- src/rhd_edid.c | 2 src/rhd_hdmi.c | 148 + src/rhd_hdmi.h | 14 src/rhd_helper.c | 32 src/rhd_i2c.c | 32 src/rhd_i2c.h | 2 src/rhd_id.c | 230 ++ src/rhd_lut.c | 153 - src/rhd_lut.h | 7 src/rhd_lvtma.c | 156 + src/rhd_mc.c | 952 +++++------- src/rhd_mc.h | 20 src/rhd_modes.c | 2 src/rhd_modes.h | 2 src/rhd_monitor.c | 21 src/rhd_monitor.h | 2 src/rhd_output.c | 115 + src/rhd_output.h | 10 src/rhd_pll.c | 26 src/rhd_pll.h | 2 src/rhd_pm.c | 475 ++++++ src/rhd_pm.h | 78 src/rhd_randr.c | 470 ++++- src/rhd_randr.h | 2 src/rhd_regs.h | 85 - src/rhd_shadow.c | 2 src/rhd_shadow.h | 2 src/rhd_tmds.c | 67 src/rhd_vga.c | 133 - src/rhd_vga.h | 21 src/rhd_video.c | 270 +++ src/rhd_video.h | 21 utils/conntest/Makefile.am | 10 utils/conntest/rhd_conntest.c | 393 ++++ utils/conntest/rhd_dump.c | 137 + 97 files changed, 16092 insertions(+), 2218 deletions(-)
New commits: commit 8cbff7bfa1201faa1e5dbf7019f17c2f4b1d2b7f Author: Matthias Hopf <mh...@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 <mh...@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 <mh...@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 <mh...@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 <mh...@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 <mh...@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 <mh...@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 <mh...@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 <e...@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 <deathsim...@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" -- To UNSUBSCRIBE, email to debian-x-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org