From 346ae57c93770205d30dd33ed621411c231ccce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Wed, 25 Feb 2009 19:12:23 +0000 Subject: [PATCH] * Stream interrupts seem to arrive too early on most HDA chips: we adjust buffer descriptors to take this into account. It defaults to one sample, but it should depend also on the sample rate or the chip vendor. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29322 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../drivers/audio/hda/hda_controller.cpp | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp b/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp index 060ad86c85..2949b576d6 100644 --- a/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp +++ b/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp @@ -109,7 +109,7 @@ stream_handle_interrupt(hda_controller* controller, hda_stream* stream) stream->real_time = system_time(); stream->frames_count += stream->buffer_length; - stream->buffer_cycle = 1 - (position / (bufferSize + 1)); // added 1 to avoid having 2 + stream->buffer_cycle = ((position / bufferSize) + 1) % stream->num_buffers; release_spinlock(&stream->lock); @@ -523,13 +523,18 @@ hda_stream_setup_buffers(hda_audio_group* audioGroup, hda_stream* stream, stream->buffer_descriptors_area = B_ERROR; } + // Stream interrupts seem to arrive too early on most HDA + // so we adjust buffer descriptors to take this into account + // TODO compute this value based on sample rate and depending on the hardware + uint32 offset = 1 * (stream->sample_size * stream->num_channels); + /* Calculate size of buffer (aligned to 128 bytes) */ bufferSize = stream->sample_size * stream->num_channels * stream->buffer_length; bufferSize = ALIGN(bufferSize, 128); - dprintf("HDA: sample size %ld, num channels %ld, buffer length %ld ****************\n", - stream->sample_size, stream->num_channels, stream->buffer_length); + dprintf("HDA: sample size %ld, num channels %ld, buffer length %ld, offset %ld **********\n", + stream->sample_size, stream->num_channels, stream->buffer_length, offset); /* Calculate total size of all buffers (aligned to size of B_PAGE_SIZE) */ alloc = bufferSize * stream->num_buffers; @@ -561,7 +566,7 @@ hda_stream_setup_buffers(hda_audio_group* audioGroup, hda_stream* stream, } /* Now allocate BDL for buffer range */ - alloc = stream->num_buffers * sizeof(bdl_entry_t); + alloc = (stream->num_buffers + ((offset > 0) ? 1 : 0)) * sizeof(bdl_entry_t); alloc = PAGE_ALIGN(alloc); stream->buffer_descriptors_area = create_area("hda buffer descriptors", @@ -585,13 +590,29 @@ hda_stream_setup_buffers(hda_audio_group* audioGroup, hda_stream* stream, dprintf("%s(%s): Allocated %ld bytes for %ld BDLEs\n", __func__, desc, alloc, stream->num_buffers); + uint32 fragments = 0; + if (offset > 0) { + bufferDescriptors->lower = stream->physical_buffers[0]; + bufferDescriptors->upper = 0; + bufferDescriptors->length = offset; + bufferDescriptors->ioc = 1; + bufferDescriptors++; + fragments++; + } + /* Setup buffer descriptor list (BDL) entries */ for (index = 0; index < stream->num_buffers; index++, bufferDescriptors++) { - bufferDescriptors->lower = stream->physical_buffers[index]; + bufferDescriptors->lower = stream->physical_buffers[index] + offset; bufferDescriptors->upper = 0; - bufferDescriptors->length = bufferSize; - bufferDescriptors->ioc = 1; + fragments++; + if (index == (stream->num_buffers - 1) && offset > 0) { + bufferDescriptors->length = bufferSize - offset; + bufferDescriptors->ioc = 0; + } else { + bufferDescriptors->length = bufferSize; + bufferDescriptors->ioc = 1; // we want an interrupt after every buffer + } } /* Configure stream registers */ @@ -624,7 +645,7 @@ hda_stream_setup_buffers(hda_audio_group* audioGroup, hda_stream* stream, stream->Write32(HDAC_STREAM_BUFFERS_BASE_LOWER, stream->physical_buffer_descriptors); stream->Write32(HDAC_STREAM_BUFFERS_BASE_UPPER, 0); - stream->Write16(HDAC_STREAM_LAST_VALID, stream->num_buffers - 1); + stream->Write16(HDAC_STREAM_LAST_VALID, fragments); /* total cyclic buffer size in _bytes_ */ stream->Write32(HDAC_STREAM_BUFFER_SIZE, bufferSize * stream->num_buffers);