From patchwork Sat Apr 10 14:52:16 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Christian_K=C3=B6nig?= X-Patchwork-Id: 91864 Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o3AEsGEw007911 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sat, 10 Apr 2010 14:54:53 GMT Received: from localhost ([127.0.0.1] helo=sfs-ml-2.v29.ch3.sourceforge.com) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1O0c2v-0007YA-0m; Sat, 10 Apr 2010 14:52:29 +0000 Received: from sfi-mx-1.v28.ch3.sourceforge.com ([172.29.28.121] helo=mx.sourceforge.net) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1O0c2t-0007Y5-Gk for dri-devel@lists.sourceforge.net; Sat, 10 Apr 2010 14:52:27 +0000 Received-SPF: pass (sfi-mx-1.v28.ch3.sourceforge.com: domain of vodafone.de designates 139.7.28.128 as permitted sender) client-ip=139.7.28.128; envelope-from=deathsimple@vodafone.de; helo=outgoing.email.vodafone.de; Received: from outgoing.email.vodafone.de ([139.7.28.128]) by sfi-mx-1.v28.ch3.sourceforge.com with esmtps (TLSv1:AES256-SHA:256) (Exim 4.69) id 1O0c2q-0007By-R7 for dri-devel@lists.sourceforge.net; Sat, 10 Apr 2010 14:52:27 +0000 X-Authentication-Info: Sender authenticated as deathsimple@vodafone.de (using PLAIN) Received: from dslb-084-060-238-131.pools.arcor-ip.net ([84.60.238.131] helo=[10.0.1.10] envelope-sender=) by SMTPIN-08.smtp.email.vodafone.de with ESMTPA id 4BC090A0.10850.218838; Sat, 10 Apr 2010 16:52:16 +0200 Subject: [PATCH] Implement IRQ support for HDMI audio From: Christian =?ISO-8859-1?Q?K=F6nig?= To: =?UTF-8?Q?Rafa=C5=82_Mi=C5=82ecki?= , "dri-devel@lists.sourceforge.net" Date: Sat, 10 Apr 2010 16:52:16 +0200 Message-ID: <1270911136.3062.7.camel@zweiundvierzig> Mime-Version: 1.0 X-Mailer: Evolution 2.28.1 X-Spam-Score: -1.5 (-) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -1.5 SPF_CHECK_PASS SPF reports sender host as permitted sender for sender-domain -0.0 SPF_PASS SPF: sender matches SPF record 0.0 DKIM_SIGNED Domain Keys Identified Mail: message has a signature X-Headers-End: 1O0c2q-0007By-R7 Cc: Alex Deucher X-BeenThere: dri-devel@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.sourceforge.net X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Sat, 10 Apr 2010 14:54:53 +0000 (UTC) >From 88ca304ef749e66961e11ee1e258ea1e001e471f 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=UTF-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önig --- drivers/gpu/drm/radeon/r600.c | 6 ++++ drivers/gpu/drm/radeon/r600_audio.c | 20 +++++++++---- drivers/gpu/drm/radeon/r600_hdmi.c | 56 ++++++++++++++++++++++++---------- drivers/gpu/drm/radeon/radeon.h | 2 + 4 files changed, 61 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 8f3454e..a275728 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2713,6 +2713,8 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *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 +2854,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..487b56b 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_device *rdev) } /* + * 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,15 @@ static void r600_audio_update_hdmi(unsigned long param) list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - if (radeon_encoder->audio_polling_active) { - still_going = 1; - if (changes || r600_hdmi_buffer_status_changed(encoder)) + int irq_pending = r600_hdmi_irq_pending(encoder); + if (irq_pending || radeon_encoder->audio_polling_active) { + still_going |= radeon_encoder->audio_polling_active; + if (irq_pending || changes || r600_hdmi_buffer_status_changed(encoder)) r600_hdmi_update_audio_settings(encoder); } } - if(still_going) - mod_timer(&rdev->audio_timer, - jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL)); + if(still_going) r600_audio_schedule_polling(rdev); } /* diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 1960ac3..8ef377a 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -278,6 +278,21 @@ int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder) } /* + * is there still an irq pending? + */ +int r600_hdmi_irq_pending(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + + if (!radeon_encoder->hdmi_offset) + return 0; + + return (RREG32(radeon_encoder->hdmi_offset + R600_HDMI_STATUS) & 0x20000000) != 0; +} + +/* * write the audio workaround status to the hardware */ void r600_hdmi_audio_workaround(struct drm_encoder *encoder) @@ -290,17 +305,15 @@ void r600_hdmi_audio_workaround(struct drm_encoder *encoder) if (!offset) return; - 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)) { - } 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); } 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); } } @@ -342,9 +355,6 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod /* 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); } /* @@ -367,6 +377,9 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder) if (!offset) return; + /* first reset any pending irq */ + WREG32_P(offset + R600_HDMI_CNTL, 0x20000000, ~0x20000000); + DRM_DEBUG("%s with %d channels, %d Hz sampling rate, %d bits per sample,\n", r600_hdmi_is_audio_buffer_filled(encoder) ? "playing" : "stopped", channels, rate, bps); @@ -413,9 +426,6 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder) r600_hdmi_audioinfoframe(encoder, channels-1, 0, 0, 0, 0, 0, 0, 0); r600_hdmi_audio_workaround(encoder); - - /* update? reset? don't realy know */ - WREG32_P(offset+R600_HDMI_CNTL, 0x04000000, ~0x04000000); } static int r600_hdmi_find_free_block(struct drm_device *dev) @@ -513,7 +523,15 @@ void r600_hdmi_enable(struct drm_encoder *encoder) } } - r600_audio_enable_polling(encoder); + if (rdev->ih.enabled) { + /* if irq is available use it */ + WREG32_P(radeon_encoder->hdmi_offset + R600_HDMI_CNTL, 0x10000000, ~0x10000000); + r600_audio_disable_polling(encoder); + } else { + /* if not fallback to polling */ + WREG32_P(radeon_encoder->hdmi_offset + R600_HDMI_CNTL, 0x0, ~0x10000000); + 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); @@ -533,11 +551,15 @@ void r600_hdmi_disable(struct drm_encoder *encoder) return; } - 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); + /* disable irq */ + WREG32_P(radeon_encoder->hdmi_offset + R600_HDMI_CNTL, 0x0, ~0x10000000); + + /* disable polling */ + r600_audio_disable_polling(encoder); + if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) { WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0, ~0x1); } else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5baf7fd..fca8e9e 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1292,6 +1292,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); @@ -1300,6 +1301,7 @@ 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_display_mode *mode); extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); +extern int r600_hdmi_irq_pending(struct drm_encoder *encoder); extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); /* evergreen */ -- 1.7.0