From: Luis R. Rodriguez <lrodriguez@atheros.com> This is based on radeonhd driver, this is a port to radeon. Cc: Egbert Eich <eich@novell.com> Cc: Matthias Hopf <mhopf@novell.com> Cc: Luc Verhaegen <libv@exsuse.de> Cc: Christian König <deathsimple@vodafone.de> Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com> --- RFT - Request For Help/patch takeover I've taken a stab at porting HDMI support from the radeonhd driver onto the radeon driver. Mind you this is my first video patch, so not sure if it was done properly. I kept telling myself I was going to finish this during my night hours but my night hours are now reserved. So if it is at least done some-what right was hoping someone could take this on themselves and complete it... The missing piece should be the generic HDMI stuff which I thought was not required but in fact is. Forgot if I compile tested.. definitely didn't try loading yet. I just rebased this onto today's git HEAD. I do have an HD4800 which I can test. Anyway, hope someone with more time can take this over. src/atombios_output.c | 2 + src/radeon.h | 96 ++++++++++ src/radeon_atombios.c | 17 ++ src/radeon_hdmi_audio.c | 442 +++++++++++++++++++++++++++++++++++++++++++++++ src/radeon_macros.h | 3 + src/radeon_probe.h | 1 + src/radeon_reg.h | 6 + 7 files changed, 567 insertions(+), 0 deletions(-) create mode 100644 src/radeon_hdmi_audio.c diff --git a/src/atombios_output.c b/src/atombios_output.c index 00d17cb..73196c0 100644 --- a/src/atombios_output.c +++ b/src/atombios_output.c @@ -1509,6 +1509,8 @@ atombios_output_mode_set(xf86OutputPtr output, atombios_output_dig_encoder_setup(output, ATOM_ENABLE); atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP); atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE); + if (atombios_get_encoder_mode(output) == ATOM_ENCODER_MODE_HDMI) + radeon_hdmi_audio_register(); break; case ENCODER_OBJECT_ID_INTERNAL_DDI: atombios_output_ddia_setup(output, ATOM_ENABLE); diff --git a/src/radeon.h b/src/radeon.h index 3c62fd9..7d280e5 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -1,6 +1,11 @@ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. + * Copyright 2008 Christian König <deathsimple@vodafone.de> + * Copyright 2007 Luc Verhaegen <libv@exsuse.de> + * Copyright 2007 Matthias Hopf <mhopf@novell.com> + * Copyright 2007 Egbert Eich <eich@novell.com> + * Copyright 2007 Advanced Micro Devices, Inc. * * All Rights Reserved. * @@ -775,6 +780,34 @@ struct radeon_accel_state { }; +struct radeon_hdmi_audio { + + int scrnIndex; + + //struct rhdHdmi* Registered; + OsTimerPtr Timer; + + Bool SavedPlaying; + int SavedChannels; + int SavedRate; + int SavedBitsPerSample; + CARD8 SavedStatusBits; + CARD8 SavedCategoryCode; + + Bool Stored; + + CARD32 StoreEnabled; + CARD32 StoreTiming; + CARD32 StoreSupportedSizeRate; + CARD32 StoreSupportedCodec; + + CARD32 StorePll1Mul; + CARD32 StorePll1Div; + CARD32 StorePll2Mul; + CARD32 StorePll2Div; + CARD32 StoreClockSrcSel; +}; + typedef struct { EntityInfoPtr pEnt; pciVideoPtr PciInfo; @@ -979,6 +1012,7 @@ typedef struct { float igp_system_mclk; float igp_ht_link_clk; float igp_ht_link_width; + struct radeon_hdmi_audio *hdmi_audio; int can_resize; void (*reemit_current2d)(ScrnInfoPtr pScrn, int op); // emit the current 2D state into the IB @@ -1005,6 +1039,53 @@ typedef struct { int bicubic_offset; } RADEONInfoRec, *RADEONInfoPtr; +/* + * used for config value of radeon_hmdi_audio_set_supported + */ +enum { + AUDIO_RATE_8000_HZ = 0x00000001, + AUDIO_RATE_11025_HZ = 0x00000002, + AUDIO_RATE_16000_HZ = 0x00000004, + AUDIO_RATE_22050_HZ = 0x00000008, + AUDIO_RATE_32000_HZ = 0x00000010, + AUDIO_RATE_44100_HZ = 0x00000020, + AUDIO_RATE_48000_HZ = 0x00000040, + AUDIO_RATE_88200_HZ = 0x00000080, + AUDIO_RATE_96000_HZ = 0x00000100, + AUDIO_RATE_176400_HZ = 0x00000200, + AUDIO_RATE_192000_HZ = 0x00000400, + AUDIO_RATE_384000_HZ = 0x00000800, + + AUDIO_BPS_8 = 0x00010000, + AUDIO_BPS_16 = 0x00020000, + AUDIO_BPS_20 = 0x00040000, + AUDIO_BPS_24 = 0x00080000, + AUDIO_BPS_32 = 0x00100000 +}; + +/* + * used for codec value of radeon_hmdi_audio_set_supported + */ +enum { + AUDIO_CODEC_PCM = 0x00000001, + AUDIO_CODEC_FLOAT32 = 0x00000002, + AUDIO_CODEC_AC3 = 0x00000004 +}; + +/* + * used for status bist value in radeon_update_hdmi_audio + */ +enum { + AUDIO_STATUS_DIG_ENABLE = 0x01, + AUDIO_STATUS_V = 0x02, + AUDIO_STATUS_VCFG = 0x04, + AUDIO_STATUS_EMPHASIS = 0x08, + AUDIO_STATUS_COPYRIGHT = 0x10, + AUDIO_STATUS_NONAUDIO = 0x20, + AUDIO_STATUS_PROFESSIONAL = 0x40, + AUDIO_STATUS_LEVEL = 0x80 +}; + #define RADEONWaitForFifo(pScrn, entries) \ do { \ if (info->accel_state->fifo_slots < entries) \ @@ -1284,6 +1365,21 @@ extern void radeon_ddx_cs_start(ScrnInfoPtr pScrn, struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix); void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo); +/* radeon_hdmi_audio.c */ +extern void radeon_hdmi_audio_init(RHDPtr rhdPtr); + +extern void radeon_hdmi_audio_set_supported(RHDPtr rhdPtr, Bool clear, CARD32 config, CARD32 codec); +extern void radeon_hdmi_audio_set_enable(RHDPtr rhdPtr, Bool Enable); +extern void radeon_hdmi_audio_set_clock(RHDPtr rhdPtr, struct rhdOutput* Output, CARD32 Clock); + +extern void radeon_hdmi_audio_register(RHDPtr rhdPtr, struct rhdHdmi* rhdHdmi); +extern void radeon_hdmi_audio_unregister(RHDPtr rhdPtr, struct rhdHdmi* rhdHdmi); + +extern void radeon_hdmi_audio_save(RHDPtr rhdPtr); +extern void radeon_hdmi_audio_restore(RHDPtr rhdPtr); + +extern void radeon_hdmi_audio_destroy(RHDPtr rhdPtr); + #ifdef XF86DRI # ifdef USE_XAA /* radeon_accelfuncs.c */ diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c index f590d5b..ff8c11d 100644 --- a/src/radeon_atombios.c +++ b/src/radeon_atombios.c @@ -1771,6 +1771,23 @@ radeon_add_encoder(ScrnInfoPtr pScrn, uint32_t encoder_id, uint32_t device_suppo } break; } + + /* This time around we'll just set the HDMI offset */ + switch (encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + info->encoders[device_index]->hdmi_offset = RADEON_HDMI_TMDS; + break; + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + info->encoders[device_index]->hdmi_offset = RADEON_HDMI_LVTMA; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + info->encoders[device_index]->hdmi_offset = RADEON_HDMI_DIG; + break; + default: + info->encoders[device_index]->hdmi_offset = 0; + break; + } return TRUE; } else { ErrorF("xalloc failed\n"); diff --git a/src/radeon_hdmi_audio.c b/src/radeon_hdmi_audio.c new file mode 100644 index 0000000..931cb6d --- /dev/null +++ b/src/radeon_hdmi_audio.c @@ -0,0 +1,442 @@ +/* + * Copyright 2009 Luis R. Rodriguez <mcgrof@gmail.com> + * Copyright 2008 Christian König <deathsimple@vodafone.de> + * Copyright 2007 Luc Verhaegen <libv@exsuse.de> + * Copyright 2007 Matthias Hopf <mhopf@novell.com> + * Copyright 2007 Egbert Eich <eich@novell.com> + * Copyright 2007 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "radeon.h" + +#define RADEON_HDMI_AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */ + +/* + * current number of channels + */ +static int radeon_hdmi_audio_channels(xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(output->scrn); + unsigned char *RADEONMMIO = info->MMIO; + return (INREG(AUDIO_RATE_BPS_CHANNEL) & 0x7) + 1; +} + +/* + * current bits per sample + */ +static int radeon_hdmi_audio_bits_per_sample(xf86OutputPtr output) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + struct radeon_hdmi_audio *Audio = radeon_output->hdmi_audio; + RADEONInfoPtr info = RADEONPTR(output->scrn); + unsigned char *RADEONMMIO = info->MMIO; + + CARD32 value = (INREG(AUDIO_RATE_BPS_CHANNEL) & 0xF0) >> 4; + switch(value) + { + case 0x0: return 8; + case 0x1: return 16; + case 0x2: return 20; + case 0x3: return 24; + case 0x4: return 32; + } + + xf86DrvMsg(Audio->scrnIndex, X_WARNING, "%s: unknown bits per sample 0x%x " + "using 16 instead.\n", __func__, (int) value); + + return 16; +} + +/* + * current sampling rate in HZ + */ +static int radeon_hdmi_audio_rate(xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(output->scrn); + unsigned char *RADEONMMIO = info->MMIO; + + CARD32 value = INREG(AUDIO_RATE_BPS_CHANNEL); + CARD32 result; + + if(value & 0x4000) + result = 44100; + else + result = 48000; + + result *= ((value >> 11) & 0x7) + 1; + result /= ((value >> 8) & 0x7) + 1; + + return result; +} + +/* + * something playing ? + */ +static Bool radeon_hdmi_audio_playing(xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(output->scrn); + unsigned char *RADEONMMIO = info->MMIO; + return (INREG(AUDIO_PLAYING) >> 4) & 1; +} + +/* + * iec 60958 status bits + */ +static CARD8 radeon_hdmi_audio_status_bits(xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(output->scrn); + unsigned char *RADEONMMIO = info->MMIO; + return INREG(AUDIO_STATUS_BITS) & 0xff; +} + +/* + * iec 60958 category code + */ +static CARD8 radeon_hdmi_audio_category_code(xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(output->scrn); + unsigned char *RADEONMMIO = info->MMIO; + return (INREG(AUDIO_STATUS_BITS) >> 8) & 0xff; +} + +/* + * update all registered hdmi interfaces with current audio parameters + */ +static CARD32 radeon_timer_hdmi_audio(OsTimerPtr timer, CARD32 time, pointer ptr) +{ + struct radeon_hdmi_audio *Audio = (struct radeon_hdmi_audio*)ptr; + Bool playing = radeon_hdmi_audio_playing(Audio); + int channels = radeon_hdmi_audio_hannels(Audio); + int rate = radeon_hdmi_audio_rate(Audio); + int bps = radeon_hdmi_audio_bits_per_sample(Audio); + CARD8 status_bits = radeon_audio_status_bits(Audio); + CARD8 category_code = radeon_audio_category_code(Audio); + + struct rhdHdmi* hdmi; + + if (playing != Audio->SavedPlaying || + channels != Audio->SavedChannels || + rate != Audio->SavedRate || + bps != Audio->SavedBitsPerSample || + status_bits != Audio->SavedStatusBits || + category_code != Audio->SavedCategoryCode) { + + Audio->SavedPlaying = playing; + Audio->SavedChannels = channels; + Audio->SavedRate = rate; + Audio->SavedBitsPerSample = bps; + Audio->SavedStatusBits = status_bits; + Audio->SavedCategoryCode = category_code; + + /* XXX: port hdmi struct usage */ + for (hdmi=Audio->Registered; hdmi != NULL; hdmi=hdmi->Next) + radeon_hdmi_update_audio_settings( + hdmi, playing, channels, + rate, bps, status_bits, + category_code); + } + + return RADEON_HDMI_AUDIO_TIMER_INTERVALL; +} + +/* + * allocate and init the audio structure + */ +void +radeon_hdmi_audio_init(xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(output->scrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + struct radeon_hdmi_audio *Audio; + + if (info->ChipFamily < CHIP_FAMILY_RS600) { + radeon_output->Audio = NULL; + return; + } + + Audio = (struct radeon_hdmi_audio *) xnfcalloc(sizeof(struct radeon_hdmi_audio), 1); + Audio->scrnIndex = info->atomBIOS->scrnIndex; + Audio->Registered = NULL; + Audio->Stored = FALSE; + + radeon_output->Audio = Audio; +} + +/* + * enable or disable the complete audio engine + */ +void +radeon_hdmi_audio_set_enable(xf86OutputPtr output, Bool Enable) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + struct radeon_hdmi_audio *Audio = radeon_output->hdmi_audio; + + if (!Audio) + return; + + REG_RMW(AUDIO_ENABLE, Enable ? 0x80000000 : 0x0, 0x80000000); + if (!Enable) { + TimerFree(Audio->Timer); + Audio->Timer = NULL; + return; + } + + /* + * the hardware generates an interrupt if audio starts/stops playing, + * but since drm doesn't support this interrupt, we check + * every RADEON_HDMI_AUDIO_TIMER_INTERVALL ms if something has changed + */ + + Audio->SavedChannels = -1; + Audio->SavedRate = -1; + Audio->SavedBitsPerSample = -1; + Audio->SavedStatusBits = 0; + Audio->SavedCategoryCode = 0; + Audio->Timer = TimerSet(NULL, 0, RADEON_HDMI_AUDIO_TIMER_INTERVALL, + radeon_hdmi_audio_update, Audio); + + /* 48kHz and 16/20 bits per sample are always supported */ + radeon_hdmi_audio_set_supported(output, TRUE, + AUDIO_RATE_48000_HZ | + AUDIO_BPS_16 | + AUDIO_BPS_20, + AUDIO_CODEC_PCM); +} + +/* + * programm the audio clock and timing registers + */ +void +radeon_hdmi_audio_set_clock(xf86OutputPtr output, CARD32 Clock) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + struct radeon_hdmi_audio *Audio = radeon_output->hdmi_audio; + radeon_encoder_ptr radeon_encoder; + RADEONInfoPtr info = RADEONPTR(output->scrn); + unsigned char *RADEONMMIO = info->MMIO; + + int Rate = 48000; + + if (!Audio) + return; + + radeon_encoder = radeon_get_encoder(output); + + xf86DrvMsg(Audio->scrnIndex, X_INFO, "%s: using %s as clock source with %d khz\n", + __func__, + device_name[radeon_get_device_index(radeon_output->active_device)], + (int) Clock); + + switch(radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + REG_RMW(AUDIO_TIMING, 0, 0x301); + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + REG_RMW(AUDIO_TIMING, 0x100, 0x301); + break; + + default: + break; + } + + switch(radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + OUTREG(AUDIO_PLL1_MUL, Rate*50); + OUTREG(AUDIO_PLL1_DIV, Clock*100); + OUTREG(AUDIO_CLK_SRCSEL, 0); + break; + + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + OUTREG(AUDIO_PLL2_MUL, Rate*50); + OUTREG(AUDIO_PLL2_DIV, Clock*100); + OUTREG(AUDIO_CLK_SRCSEL, 1); + break; + + default: + xf86DrvMsg(Audio->scrnIndex, X_ERROR, "%s: unsupported output type\n", __func__); + break; + } +} + +/* + * set the supported audio rates, bits per sample and codecs + */ +void +radeon_hdmi_audio_set_supported(xf86OutputPtr output, Bool clear, CARD32 config, CARD32 codec) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + struct radeon_hdmi_audio *Audio = radeon_output->hdmi_audio; + RADEONInfoPtr info = RADEONPTR(output->scrn); + unsigned char *RADEONMMIO = info->MMIO; + + if (!Audio) + return; + + xf86DrvMsg(Audio->scrnIndex, X_INFO, "%s: config 0x%x codec 0x%x\n", + __func__, (int) config, (int) codec); + + if(config & 0xFFE0F000) + xf86DrvMsg(Audio->scrnIndex, X_WARNING, "%s: reserved config bits set 0x%x\n", + __func__, (int) config); + + if(codec & 0xFFFFFFF8) + xf86DrvMsg(Audio->scrnIndex, X_WARNING, "%s: reserved codec bits set 0x%x\n", + __func__, (int) codec); + + if (clear) { + OUTREG(AUDIO_SUPPORTED_SIZE_RATE, config); + OUTREG(AUDIO_SUPPORTED_CODEC, codec); + } else { + OUTREG(AUDIO_SUPPORTED_SIZE_RATE, config, config); + OUTREG(AUDIO_SUPPORTED_CODEC, codec, codec); + } +} + +/* + * register and hdmi interface for getting updates when audio parameters change. + * The right approach here is to use DRM interrupts for Audio updates but until + * DRM does not suppor that we use a timer to update it regularly. + */ +void radeon_hdmi_audio_register(xf86OutputPtr output, struct rhdHdmi* rhdHdmi) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + struct radeon_hdmi_audio *Audio = radeon_output->hdmi_audio; + + if (!Audio) + return; + + /* XXX: How to port rhdHmdi to ati driver from radeonhd */ + if(!rhdHdmi) + return; + + rhdHdmi->Next = Audio->Registered; + Audio->Registered = rhdHdmi; +} + + +/* + * unregister the hdmi interface + */ +void radeon_hdmi_audio_unregister(xf86OutputPtr output, struct rhdHdmi* rhdHdmi) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + struct radeon_hdmi_audio *Audio = radeon_output->hdmi_audio; + struct rhdHdmi** hdmiPtr; + + if (!Audio) + return; + + for (hdmiPtr=&Audio->Registered; hdmiPtr!=NULL; hdmiPtr=&(*hdmiPtr)->Next) { + if(*hdmiPtr != rhdHdmi) + continue; + *hdmiPtr = rhdHdmi->Next; + rhdHdmi->Next = NULL; + return; + } + +} + +/* + * save the current config of audio engine + */ +void +radeon_hdmi_audio_save(xf86OutputPtr output) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + struct radeon_hdmi_audio *Audio = radeon_output->hdmi_audio; + unsigned char *RADEONMMIO = info->MMIO; + + if (!Audio) + return; + + Audio->StoreEnabled = INREG(AUDIO_ENABLE); + Audio->StoreTiming = INREG(AUDIO_TIMING); + + Audio->StoreSupportedSizeRate = INREG(AUDIO_SUPPORTED_SIZE_RATE); + Audio->StoreSupportedCodec = INREG(AUDIO_SUPPORTED_CODEC); + + Audio->StorePll1Mul = INREG(AUDIO_PLL1_MUL); + Audio->StorePll1Div = INREG(AUDIO_PLL1_DIV); + Audio->StorePll2Mul = INREG(AUDIO_PLL2_MUL); + Audio->StorePll2Div = INREG(AUDIO_PLL2_DIV); + Audio->StoreClockSrcSel = INREG(AUDIO_CLK_SRCSEL); + + Audio->Stored = TRUE; +} + +/* + * restore the saved config of audio engine + */ +void +radeon_hdmi_audio_restore(xf86OutputPtr output) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + struct radeon_hdmi_audio *Audio = radeon_output->hdmi_audio; + RADEONInfoPtr info = RADEONPTR(output->scrn); + unsigned char *RADEONMMIO = info->MMIO; + + if (!Audio) + return; + + if (!Audio->Stored) { + xf86DrvMsg(Audio->scrnIndex, X_ERROR, "%s: trying to restore " + "uninitialized values.\n", __func__); + return; + } + + /* shoutdown the audio engine before doing anything else */ + radeon_hdmi_audio_set_enable(output, FALSE); + + OUTREG(AUDIO_TIMING, Audio->StoreTiming); + OUTREG(AUDIO_SUPPORTED_SIZE_RATE, Audio->StoreSupportedSizeRate); + OUTREG(AUDIO_SUPPORTED_CODEC, Audio->StoreSupportedCodec); + + OUTREG(AUDIO_PLL1_MUL, Audio->StorePll1Mul); + OUTREG(AUDIO_PLL1_DIV, Audio->StorePll1Div); + OUTREG(AUDIO_PLL2_MUL, Audio->StorePll2Mul); + OUTREG(AUDIO_PLL2_DIV, Audio->StorePll2Div); + OUTREG(AUDIO_CLK_SRCSEL, Audio->StoreClockSrcSel); + OUTREG(AUDIO_ENABLE, Audio->StoreEnabled); +} + +/* + * release the allocated memory + */ +void +radeon_hdmi_audio_destroy(xf86OutputPtr output) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (!radeon_output->hdmi_audio) + return; + + if(radeon_output->hdmi_audio->Timer) + TimerFree(radeon_output->hdmi_audio->Timer); + + xfree(radeon_output->hdmi_audio); + radeon_output->hdmi_audio = NULL; +} diff --git a/src/radeon_macros.h b/src/radeon_macros.h index 26d9825..a51f2f4 100644 --- a/src/radeon_macros.h +++ b/src/radeon_macros.h @@ -69,6 +69,9 @@ #define ADDRREG(addr) ((volatile uint32_t *)(pointer)(RADEONMMIO + (addr))) +#define REG_RMW(_r, _m, _v) \ + OUTREG((_r), \ + (INREG(_r) & ~_m) | ((_v) & _m)) #define OUTREGP(addr, val, mask) \ do { \ diff --git a/src/radeon_probe.h b/src/radeon_probe.h index 9cac15c..b62f019 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -167,6 +167,7 @@ typedef struct _RADEONCrtcPrivateRec { typedef struct _radeon_encoder { uint16_t encoder_id; int devices; + uint32_t hdmi_offset; void *dev_priv; } radeon_encoder_rec, *radeon_encoder_ptr; diff --git a/src/radeon_reg.h b/src/radeon_reg.h index 9df7fff..0e1e9a4 100644 --- a/src/radeon_reg.h +++ b/src/radeon_reg.h @@ -3833,6 +3833,12 @@ #define AVIVO_D2SCL_SCALER_TAP_CONTROL 0x6d94 #define AVIVO_D2SCL_UPDATE 0x6dcc +/* HDMI offsets */ +#define RADEON_HDMI_TMDS 0x7400 +#define RADEON_HDMI_LVTMA 0x7700 +#define RADEON_HDMI_DIG 0x7800 + + #define AVIVO_DDIA_BIT_DEPTH_CONTROL 0x7214 #define AVIVO_DACA_ENABLE 0x7800 -- 1.6.3.3 -- To unsubscribe, e-mail: radeonhd+unsubscribe@opensuse.org For additional commands, e-mail: radeonhd+help@opensuse.org