From mboxrd@z Thu Jan 1 00:00:00 1970 From: Christian =?ISO-8859-1?Q?K=F6nig?= Subject: [PATCH] Implement IRQ support for HDMI audio (Ver 2) Date: Tue, 13 Apr 2010 20:52:59 +0200 Message-ID: <1271184780.2480.14.camel@zweiundvierzig> References: <1270911136.3062.7.camel@zweiundvierzig> <1271115105.2296.2.camel@zweiundvierzig> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-VYYFp3IBNPM0oUs0ZLoy" Return-path: In-Reply-To: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.sourceforge.net To: "dri-devel@lists.sourceforge.net" Cc: Alex Deucher List-Id: dri-devel@lists.freedesktop.org --=-VYYFp3IBNPM0oUs0ZLoy Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit Hi, attached is the next version of the IRQ support patch for HDMI audio on radeon hardware. The following changes (mostly suggested by Alex) were made: 1. Using the common asic irq functions now. 2. Using rdev->irq.installed instead of rdev->ih.enabled. 3. Disabling irq support for RS600/690/740 were it isn't expected to be working. 4. Start using defines for the individual bits instead of spreading magic numbers all around. A drawback is that I still couldn't find the time to test it my RV710. Christian. --=-VYYFp3IBNPM0oUs0ZLoy Content-Disposition: attachment; filename="0001-drm-radeon-kms-rework-audio-polling-timer.patch" Content-Type: text/x-patch; name="0001-drm-radeon-kms-rework-audio-polling-timer.patch"; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-MIME-Autoconverted: from 8bit to quoted-printable by outgoing.email.vodafone.de id o3DIr1Qi000875 >>From cc9ec18c9e31b1bd0ca19b5729ffed1e3b4a6e2d Mon Sep 17 00:00:00 2001 From: =3D?UTF-8?q?Christian=3D20K=3DC3=3DB6nig?=3D Date: Mon, 5 Apr 2010 22:14:55 +0200 Subject: [PATCH 1/2] drm/radeon/kms: rework audio polling timer MIME-Version: 1.0 Content-Type: text/plain; charset=3DUTF-8 Content-Transfer-Encoding: 8bit Rework HDMI audio polling timer, only enable it when at least one HDMI encoder needs it. Preparation for replacing it with irq support. Signed-off-by: Christian K=C3=B6nig --- drivers/gpu/drm/radeon/r600_audio.c | 55 +++++++++++++++++++++++++---= ----- drivers/gpu/drm/radeon/r600_hdmi.c | 17 +++++++---- drivers/gpu/drm/radeon/radeon.h | 14 +++++---- drivers/gpu/drm/radeon/radeon_mode.h | 1 + 4 files changed, 61 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon= /r600_audio.c index dac7042..03bf8bc 100644 --- a/drivers/gpu/drm/radeon/r600_audio.c +++ b/drivers/gpu/drm/radeon/r600_audio.c @@ -44,7 +44,7 @@ static int r600_audio_chipset_supported(struct radeon_d= evice *rdev) /* * current number of channels */ -static int r600_audio_channels(struct radeon_device *rdev) +int r600_audio_channels(struct radeon_device *rdev) { return (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0x7) + 1; } @@ -52,7 +52,7 @@ static int r600_audio_channels(struct radeon_device *rd= ev) /* * current bits per sample */ -static int r600_audio_bits_per_sample(struct radeon_device *rdev) +int r600_audio_bits_per_sample(struct radeon_device *rdev) { uint32_t value =3D (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0xF0) >> 4; switch (value) { @@ -71,7 +71,7 @@ static int r600_audio_bits_per_sample(struct radeon_dev= ice *rdev) /* * current sampling rate in HZ */ -static int r600_audio_rate(struct radeon_device *rdev) +int r600_audio_rate(struct radeon_device *rdev) { uint32_t value =3D RREG32(R600_AUDIO_RATE_BPS_CHANNEL); uint32_t result; @@ -90,7 +90,7 @@ static int r600_audio_rate(struct radeon_device *rdev) /* * iec 60958 status bits */ -static uint8_t r600_audio_status_bits(struct radeon_device *rdev) +uint8_t r600_audio_status_bits(struct radeon_device *rdev) { return RREG32(R600_AUDIO_STATUS_BITS) & 0xff; } @@ -98,7 +98,7 @@ static uint8_t r600_audio_status_bits(struct radeon_dev= ice *rdev) /* * iec 60958 category code */ -static uint8_t r600_audio_category_code(struct radeon_device *rdev) +uint8_t r600_audio_category_code(struct radeon_device *rdev) { return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff; } @@ -118,7 +118,7 @@ static void r600_audio_update_hdmi(unsigned long para= m) uint8_t category_code =3D r600_audio_category_code(rdev); =20 struct drm_encoder *encoder; - int changes =3D 0; + int changes =3D 0, still_going =3D 0; =20 changes |=3D channels !=3D rdev->audio_channels; changes |=3D rate !=3D rdev->audio_rate; @@ -135,15 +135,17 @@ static void r600_audio_update_hdmi(unsigned long pa= ram) } =20 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - if (changes || r600_hdmi_buffer_status_changed(encoder)) - r600_hdmi_update_audio_settings( - encoder, channels, - rate, bps, status_bits, - category_code); + struct radeon_encoder *radeon_encoder =3D to_radeon_encoder(encoder); + if (radeon_encoder->audio_polling_active) { + still_going =3D 1; + if (changes || r600_hdmi_buffer_status_changed(encoder)) + r600_hdmi_update_audio_settings(encoder); + } } =20 - mod_timer(&rdev->audio_timer, - jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL)); + if(still_going) + mod_timer(&rdev->audio_timer, + jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL)); } =20 /* @@ -176,9 +178,34 @@ int r600_audio_init(struct radeon_device *rdev) r600_audio_update_hdmi, (unsigned long)rdev); =20 + return 0; +} + +/* + * enable the polling timer, to check for status changes + */ +void r600_audio_enable_polling(struct drm_encoder *encoder) +{ + struct drm_device *dev =3D encoder->dev; + struct radeon_device *rdev =3D dev->dev_private; + struct radeon_encoder *radeon_encoder =3D to_radeon_encoder(encoder); + + DRM_DEBUG("r600_audio_enable_polling: %d", radeon_encoder->audio_pollin= g_active); + if (radeon_encoder->audio_polling_active) + return; + + radeon_encoder->audio_polling_active =3D 1; mod_timer(&rdev->audio_timer, jiffies + 1); +} =20 - return 0; +/* + * disable the polling timer, so we get no more status updates + */ +void r600_audio_disable_polling(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder =3D to_radeon_encoder(encoder); + DRM_DEBUG("r600_audio_disable_polling: %d", radeon_encoder->audio_polli= ng_active); + radeon_encoder->audio_polling_active =3D 0; } =20 /* diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/= r600_hdmi.c index 029fa14..1960ac3 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -350,17 +350,18 @@ void r600_hdmi_setmode(struct drm_encoder *encoder,= struct drm_display_mode *mod /* * update settings with current parameters from audio engine */ -void r600_hdmi_update_audio_settings(struct drm_encoder *encoder, - int channels, - int rate, - int bps, - uint8_t status_bits, - uint8_t category_code) +void r600_hdmi_update_audio_settings(struct drm_encoder *encoder) { struct drm_device *dev =3D encoder->dev; struct radeon_device *rdev =3D dev->dev_private; uint32_t offset =3D to_radeon_encoder(encoder)->hdmi_offset; =20 + int channels =3D r600_audio_channels(rdev); + int rate =3D r600_audio_rate(rdev); + int bps =3D r600_audio_bits_per_sample(rdev); + uint8_t status_bits =3D r600_audio_status_bits(rdev); + uint8_t category_code =3D r600_audio_category_code(rdev); + uint32_t iec; =20 if (!offset) @@ -512,6 +513,8 @@ void r600_hdmi_enable(struct drm_encoder *encoder) } } =20 + r600_audio_enable_polling(encoder); + DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n", radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); } @@ -530,6 +533,8 @@ void r600_hdmi_disable(struct drm_encoder *encoder) return; } =20 + r600_audio_disable_polling(encoder); + DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n", radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); =20 diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/rad= eon.h index 034218c..5baf7fd 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1287,18 +1287,20 @@ extern void r600_irq_suspend(struct radeon_device= *rdev); extern int r600_audio_init(struct radeon_device *rdev); extern int r600_audio_tmds_index(struct drm_encoder *encoder); extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock)= ; +extern int r600_audio_channels(struct radeon_device *rdev); +extern int r600_audio_bits_per_sample(struct radeon_device *rdev); +extern int r600_audio_rate(struct radeon_device *rdev); +extern uint8_t r600_audio_status_bits(struct radeon_device *rdev); +extern uint8_t r600_audio_category_code(struct radeon_device *rdev); +extern void r600_audio_enable_polling(struct drm_encoder *encoder); +extern void r600_audio_disable_polling(struct drm_encoder *encoder); extern void r600_audio_fini(struct radeon_device *rdev); extern void r600_hdmi_init(struct drm_encoder *encoder); extern void r600_hdmi_enable(struct drm_encoder *encoder); extern void r600_hdmi_disable(struct drm_encoder *encoder); extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_di= splay_mode *mode); extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); -extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder, - int channels, - int rate, - int bps, - uint8_t status_bits, - uint8_t category_code); +extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)= ; =20 /* evergreen */ struct evergreen_mc_save { diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeo= n/radeon_mode.h index 0b8e327..715bfb7 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -339,6 +339,7 @@ struct radeon_encoder { enum radeon_rmx_type rmx_type; struct drm_display_mode native_mode; void *enc_priv; + int audio_polling_active; int hdmi_offset; int hdmi_config_offset; int hdmi_audio_workaround; --=20 1.7.0 --=-VYYFp3IBNPM0oUs0ZLoy Content-Disposition: attachment; filename="0002-drm-radeon-kms-HDMI-irq-support.patch" Content-Type: text/x-patch; name="0002-drm-radeon-kms-HDMI-irq-support.patch"; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-MIME-Autoconverted: from 8bit to quoted-printable by outgoing.email.vodafone.de id o3DIr1Qi000875 >>From 1658a5093ee03b951738ac376a3fafb5707d279b Mon Sep 17 00:00:00 2001 From: Christian Koenig Date: Sat, 10 Apr 2010 03:13:16 +0200 Subject: [PATCH 2/2] drm/radeon/kms: HDMI irq support MIME-Version: 1.0 Content-Type: text/plain; charset=3DUTF-8 Content-Transfer-Encoding: 8bit Implements irq support for HDMI audio output. Now the polling timer is only enabled if irq support isn't available. Signed-off-by: Christian K=C3=B6nig --- drivers/gpu/drm/radeon/r600.c | 33 ++++++++++++++++++++ drivers/gpu/drm/radeon/r600_audio.c | 21 ++++++++----- drivers/gpu/drm/radeon/r600_hdmi.c | 53 +++++++++++++++++++----------= --- drivers/gpu/drm/radeon/r600_reg.h | 57 ++++++++++++++++++-----------= ----- drivers/gpu/drm/radeon/radeon.h | 3 ++ 5 files changed, 111 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.= c index 8f3454e..421b485 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2500,6 +2500,7 @@ int r600_irq_set(struct radeon_device *rdev) u32 cp_int_cntl =3D CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; u32 mode_int =3D 0; u32 hpd1, hpd2, hpd3, hpd4 =3D 0, hpd5 =3D 0, hpd6 =3D 0; + u32 hdmi1, hdmi2; =20 if (!rdev->irq.installed) { WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n"); @@ -2513,7 +2514,9 @@ int r600_irq_set(struct radeon_device *rdev) return 0; } =20 + hdmi1 =3D RREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN= ; if (ASIC_IS_DCE3(rdev)) { + hdmi2 =3D RREG32(R600_HDMI_BLOCK3 + R600_HDMI_CNTL) & ~R600_HDMI_INT_E= N; hpd1 =3D RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd2 =3D RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd3 =3D RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN; @@ -2523,6 +2526,7 @@ int r600_irq_set(struct radeon_device *rdev) hpd6 =3D RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; } } else { + hdmi2 =3D RREG32(R600_HDMI_BLOCK2 + R600_HDMI_CNTL) & ~R600_HDMI_INT_E= N; hpd1 =3D RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd2 =3D RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd3 =3D RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN; @@ -2564,10 +2568,20 @@ int r600_irq_set(struct radeon_device *rdev) DRM_DEBUG("r600_irq_set: hpd 6\n"); hpd6 |=3D DC_HPDx_INT_EN; } + if (rdev->irq.hdmi[0]) { + DRM_DEBUG("r600_irq_set: hdmi 1\n"); + hdmi1 |=3D R600_HDMI_INT_EN; + } + if (rdev->irq.hdmi[1]) { + DRM_DEBUG("r600_irq_set: hdmi 2\n"); + hdmi2 |=3D R600_HDMI_INT_EN; + } =20 WREG32(CP_INT_CNTL, cp_int_cntl); WREG32(DxMODE_INT_MASK, mode_int); + WREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, hdmi1); if (ASIC_IS_DCE3(rdev)) { + WREG32(R600_HDMI_BLOCK3 + R600_HDMI_CNTL, hdmi2); WREG32(DC_HPD1_INT_CONTROL, hpd1); WREG32(DC_HPD2_INT_CONTROL, hpd2); WREG32(DC_HPD3_INT_CONTROL, hpd3); @@ -2577,6 +2591,7 @@ int r600_irq_set(struct radeon_device *rdev) WREG32(DC_HPD6_INT_CONTROL, hpd6); } } else { + WREG32(R600_HDMI_BLOCK2 + R600_HDMI_CNTL, hdmi2); WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1); WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, hpd3); @@ -2660,6 +2675,18 @@ static inline void r600_irq_ack(struct radeon_devi= ce *rdev, WREG32(DC_HPD6_INT_CONTROL, tmp); } } + if (RREG32(R600_HDMI_BLOCK1 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING= ) { + WREG32_P(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_H= DMI_INT_ACK); + } + if (ASIC_IS_DCE3(rdev)) { + if (RREG32(R600_HDMI_BLOCK3 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDIN= G) { + WREG32_P(R600_HDMI_BLOCK3 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_= HDMI_INT_ACK); + } + } else { + if (RREG32(R600_HDMI_BLOCK2 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDIN= G) { + WREG32_P(R600_HDMI_BLOCK2 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_= HDMI_INT_ACK); + } + } } =20 void r600_irq_disable(struct radeon_device *rdev) @@ -2713,6 +2740,8 @@ static inline u32 r600_get_ih_wptr(struct radeon_de= vice *rdev) * 19 1 FP Hot plug detection B * 19 2 DAC A auto-detection * 19 3 DAC B auto-detection + * 21 4 HDMI block A + * 21 5 HDMI block B * 176 - CP_INT RB * 177 - CP_INT IB1 * 178 - CP_INT IB2 @@ -2852,6 +2881,10 @@ restart_ih: break; } break; + case 21: /* HDMI */ + DRM_DEBUG("IH: HDMI: 0x%x\n", src_data); + r600_audio_schedule_polling(rdev); + break; case 176: /* CP_INT in ring buffer */ case 177: /* CP_INT in IB1 */ case 178: /* CP_INT in IB2 */ diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon= /r600_audio.c index 03bf8bc..89d8dc9 100644 --- a/drivers/gpu/drm/radeon/r600_audio.c +++ b/drivers/gpu/drm/radeon/r600_audio.c @@ -104,6 +104,15 @@ uint8_t r600_audio_category_code(struct radeon_devic= e *rdev) } =20 /* + * schedule next audio update event + */ +void r600_audio_schedule_polling(struct radeon_device *rdev) +{ + mod_timer(&rdev->audio_timer, + jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL)); +} + +/* * update all hdmi interfaces with current audio parameters */ static void r600_audio_update_hdmi(unsigned long param) @@ -136,16 +145,12 @@ static void r600_audio_update_hdmi(unsigned long pa= ram) =20 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { struct radeon_encoder *radeon_encoder =3D to_radeon_encoder(encoder); - if (radeon_encoder->audio_polling_active) { - still_going =3D 1; - if (changes || r600_hdmi_buffer_status_changed(encoder)) - r600_hdmi_update_audio_settings(encoder); - } + still_going |=3D radeon_encoder->audio_polling_active; + if (changes || r600_hdmi_buffer_status_changed(encoder)) + r600_hdmi_update_audio_settings(encoder); } =20 - if(still_going) - mod_timer(&rdev->audio_timer, - jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL)); + if(still_going) r600_audio_schedule_polling(rdev); } =20 /* diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/= r600_hdmi.c index 1960ac3..753c9a9 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -290,17 +290,15 @@ void r600_hdmi_audio_workaround(struct drm_encoder = *encoder) if (!offset) return; =20 - if (r600_hdmi_is_audio_buffer_filled(encoder)) { - /* disable audio workaround and start delivering of audio frames */ - WREG32_P(offset+R600_HDMI_CNTL, 0x00000001, ~0x00001001); + if (!radeon_encoder->hdmi_audio_workaround || + r600_hdmi_is_audio_buffer_filled(encoder)) { =20 - } else if (radeon_encoder->hdmi_audio_workaround) { - /* enable audio workaround and start delivering of audio frames */ - WREG32_P(offset+R600_HDMI_CNTL, 0x00001001, ~0x00001001); + /* disable audio workaround */ + WREG32_P(offset+R600_HDMI_CNTL, 0x00000001, ~0x00001001); =20 } else { - /* disable audio workaround and stop delivering of audio frames */ - WREG32_P(offset+R600_HDMI_CNTL, 0x00000000, ~0x00001001); + /* enable audio workaround */ + WREG32_P(offset+R600_HDMI_CNTL, 0x00001001, ~0x00001001); } } =20 @@ -342,9 +340,6 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, s= truct drm_display_mode *mod =20 /* audio packets per line, does anyone know how to calc this ? */ WREG32_P(offset+R600_HDMI_CNTL, 0x00040000, ~0x001F0000); - - /* update? reset? don't realy know */ - WREG32_P(offset+R600_HDMI_CNTL, 0x14000000, ~0x14000000); } =20 /* @@ -413,9 +408,6 @@ void r600_hdmi_update_audio_settings(struct drm_encod= er *encoder) r600_hdmi_audioinfoframe(encoder, channels-1, 0, 0, 0, 0, 0, 0, 0); =20 r600_hdmi_audio_workaround(encoder); - - /* update? reset? don't realy know */ - WREG32_P(offset+R600_HDMI_CNTL, 0x04000000, ~0x04000000); } =20 static int r600_hdmi_find_free_block(struct drm_device *dev) @@ -484,6 +476,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder) struct drm_device *dev =3D encoder->dev; struct radeon_device *rdev =3D dev->dev_private; struct radeon_encoder *radeon_encoder =3D to_radeon_encoder(encoder); + uint32_t offset; =20 if (!radeon_encoder->hdmi_offset) { r600_hdmi_assign_block(encoder); @@ -494,10 +487,10 @@ void r600_hdmi_enable(struct drm_encoder *encoder) } } =20 + offset =3D radeon_encoder->hdmi_offset; if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) { WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0x1, ~0x1); } else if (rdev->family >=3D CHIP_R600 && !ASIC_IS_DCE3(rdev)) { - int offset =3D radeon_encoder->hdmi_offset; switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: WREG32_P(AVIVO_TMDSA_CNTL, 0x4, ~0x4); @@ -513,7 +506,20 @@ void r600_hdmi_enable(struct drm_encoder *encoder) } } =20 - r600_audio_enable_polling(encoder); + if (rdev->irq.installed + && rdev->family !=3D CHIP_RS600 + && rdev->family !=3D CHIP_RS690 + && rdev->family !=3D CHIP_RS740) { + + /* if irq is available use it */ + rdev->irq.hdmi[offset =3D=3D R600_HDMI_BLOCK1 ? 0 : 1] =3D true; + radeon_irq_set(rdev); + + r600_audio_disable_polling(encoder); + } else { + /* if not fallback to polling */ + r600_audio_enable_polling(encoder); + } =20 DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n", radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); @@ -527,21 +533,26 @@ void r600_hdmi_disable(struct drm_encoder *encoder) struct drm_device *dev =3D encoder->dev; struct radeon_device *rdev =3D dev->dev_private; struct radeon_encoder *radeon_encoder =3D to_radeon_encoder(encoder); + uint8_t offset =3D radeon_encoder->hdmi_offset; =20 - if (!radeon_encoder->hdmi_offset) { + if (!offset) { dev_err(rdev->dev, "Disabling not enabled HDMI\n"); return; } =20 - r600_audio_disable_polling(encoder); - DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n", - radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); + offset, radeon_encoder->encoder_id); + + /* disable irq */ + rdev->irq.hdmi[offset =3D=3D R600_HDMI_BLOCK1 ? 0 : 1] =3D false; + radeon_irq_set(rdev); + + /* disable polling */ + r600_audio_disable_polling(encoder); =20 if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) { WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0, ~0x1); } else if (rdev->family >=3D CHIP_R600 && !ASIC_IS_DCE3(rdev)) { - int offset =3D radeon_encoder->hdmi_offset; switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: WREG32_P(AVIVO_TMDSA_CNTL, 0, ~0x4); diff --git a/drivers/gpu/drm/radeon/r600_reg.h b/drivers/gpu/drm/radeon/r= 600_reg.h index 7b1d223..d84612a 100644 --- a/drivers/gpu/drm/radeon/r600_reg.h +++ b/drivers/gpu/drm/radeon/r600_reg.h @@ -157,33 +157,36 @@ #define R600_HDMI_BLOCK3 0x7800 =20 /* HDMI registers */ -#define R600_HDMI_ENABLE 0x00 -#define R600_HDMI_STATUS 0x04 -#define R600_HDMI_CNTL 0x08 -#define R600_HDMI_UNKNOWN_0 0x0C -#define R600_HDMI_AUDIOCNTL 0x10 -#define R600_HDMI_VIDEOCNTL 0x14 -#define R600_HDMI_VERSION 0x18 -#define R600_HDMI_UNKNOWN_1 0x28 -#define R600_HDMI_VIDEOINFOFRAME_0 0x54 -#define R600_HDMI_VIDEOINFOFRAME_1 0x58 -#define R600_HDMI_VIDEOINFOFRAME_2 0x5c -#define R600_HDMI_VIDEOINFOFRAME_3 0x60 -#define R600_HDMI_32kHz_CTS 0xac -#define R600_HDMI_32kHz_N 0xb0 -#define R600_HDMI_44_1kHz_CTS 0xb4 -#define R600_HDMI_44_1kHz_N 0xb8 -#define R600_HDMI_48kHz_CTS 0xbc -#define R600_HDMI_48kHz_N 0xc0 -#define R600_HDMI_AUDIOINFOFRAME_0 0xcc -#define R600_HDMI_AUDIOINFOFRAME_1 0xd0 -#define R600_HDMI_IEC60958_1 0xd4 -#define R600_HDMI_IEC60958_2 0xd8 -#define R600_HDMI_UNKNOWN_2 0xdc -#define R600_HDMI_AUDIO_DEBUG_0 0xe0 -#define R600_HDMI_AUDIO_DEBUG_1 0xe4 -#define R600_HDMI_AUDIO_DEBUG_2 0xe8 -#define R600_HDMI_AUDIO_DEBUG_3 0xec +#define R600_HDMI_ENABLE 0x00 +#define R600_HDMI_STATUS 0x04 +# define R600_HDMI_INT_PENDING (1 << 29) +#define R600_HDMI_CNTL 0x08 +# define R600_HDMI_INT_EN (1 << 28) +# define R600_HDMI_INT_ACK (1 << 29) +#define R600_HDMI_UNKNOWN_0 0x0C +#define R600_HDMI_AUDIOCNTL 0x10 +#define R600_HDMI_VIDEOCNTL 0x14 +#define R600_HDMI_VERSION 0x18 +#define R600_HDMI_UNKNOWN_1 0x28 +#define R600_HDMI_VIDEOINFOFRAME_0 0x54 +#define R600_HDMI_VIDEOINFOFRAME_1 0x58 +#define R600_HDMI_VIDEOINFOFRAME_2 0x5c +#define R600_HDMI_VIDEOINFOFRAME_3 0x60 +#define R600_HDMI_32kHz_CTS 0xac +#define R600_HDMI_32kHz_N 0xb0 +#define R600_HDMI_44_1kHz_CTS 0xb4 +#define R600_HDMI_44_1kHz_N 0xb8 +#define R600_HDMI_48kHz_CTS 0xbc +#define R600_HDMI_48kHz_N 0xc0 +#define R600_HDMI_AUDIOINFOFRAME_0 0xcc +#define R600_HDMI_AUDIOINFOFRAME_1 0xd0 +#define R600_HDMI_IEC60958_1 0xd4 +#define R600_HDMI_IEC60958_2 0xd8 +#define R600_HDMI_UNKNOWN_2 0xdc +#define R600_HDMI_AUDIO_DEBUG_0 0xe0 +#define R600_HDMI_AUDIO_DEBUG_1 0xe4 +#define R600_HDMI_AUDIO_DEBUG_2 0xe8 +#define R600_HDMI_AUDIO_DEBUG_3 0xec =20 /* HDMI additional config base register addresses */ #define R600_HDMI_CONFIG1 0x7600 diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/rad= eon.h index 5baf7fd..1fefd2b 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -375,6 +375,8 @@ struct radeon_irq { wait_queue_head_t vblank_queue; /* FIXME: use defines for max hpd/dacs */ bool hpd[6]; + /* FIXME: use defines for max HDMI blocks */ + bool hdmi[2]; spinlock_t sw_lock; int sw_refcount; }; @@ -1292,6 +1294,7 @@ extern int r600_audio_bits_per_sample(struct radeon= _device *rdev); extern int r600_audio_rate(struct radeon_device *rdev); extern uint8_t r600_audio_status_bits(struct radeon_device *rdev); extern uint8_t r600_audio_category_code(struct radeon_device *rdev); +extern void r600_audio_schedule_polling(struct radeon_device *rdev); extern void r600_audio_enable_polling(struct drm_encoder *encoder); extern void r600_audio_disable_polling(struct drm_encoder *encoder); extern void r600_audio_fini(struct radeon_device *rdev); --=20 1.7.0 --=-VYYFp3IBNPM0oUs0ZLoy Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline ------------------------------------------------------------------------------ Download Intel® Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev --=-VYYFp3IBNPM0oUs0ZLoy Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline -- _______________________________________________ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel --=-VYYFp3IBNPM0oUs0ZLoy--