[haiku-commits] r34633 - haiku/trunk/src/add-ons/kernel/drivers/audio/hda

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 11 Dec 2009 17:16:45 +0100 (CET)

Author: bonefish
Date: 2009-12-11 17:16:44 +0100 (Fri, 11 Dec 2009)
New Revision: 34633
Changeset: http://dev.haiku-os.org/changeset/34633/haiku

Modified:
   haiku/trunk/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp
Log:
* buffer_ready_sem was released with B_DO_NOT_RESCHEDULE, but without
  returning B_INVOKE_SCHEDULER from the interrupt handler, causing
  latencies up to a full quantum for the multi audio output thread. This
  change improves audio clicks quite a bit on my machine. Though they still
  happen from time to time and particulary on FS activity.
* Automatic whitespace cleanup.


Modified: haiku/trunk/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp 
2009-12-11 15:38:13 UTC (rev 34632)
+++ haiku/trunk/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp 
2009-12-11 16:16:44 UTC (rev 34633)
@@ -82,19 +82,21 @@
 }
 
 
-//! Called with interrupts off
-static void
+/*! Called with interrupts off.
+       Returns \c true, if the scheduler shall be invoked.
+*/
+static bool
 stream_handle_interrupt(hda_controller* controller, hda_stream* stream)
 {
        uint8 status;
        uint32 position, bufferSize;
 
        if (!stream->running)
-               return;
+               return false;
 
        status = stream->Read8(HDAC_STREAM_STATUS);
        if (status == 0)
-               return;
+               return false;
 
        stream->Write8(HDAC_STREAM_STATUS, status);
 
@@ -105,11 +107,11 @@
 
        if ((status & STATUS_BUFFER_COMPLETED) == 0) {
                dprintf("hda: stream buffer not completed (id:%ld)\n", 
stream->id);
-               return;
+               return false;
        }
 
        position = stream->Read32(HDAC_STREAM_POSITION);
-       bufferSize = ALIGN(stream->sample_size * stream->num_channels 
+       bufferSize = ALIGN(stream->sample_size * stream->num_channels
                * stream->buffer_length, 128);
 
        // Buffer Completed Interrupt
@@ -122,13 +124,15 @@
        release_spinlock(&stream->lock);
 
        release_sem_etc(controller->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE);
-       
-       if (stream->warn_count < 20 
+
+       if (stream->warn_count < 20
                && (position - stream->buffer_cycle * bufferSize) > (bufferSize 
>> 1)) {
                dprintf("hda: stream incorrect position %ld %ld %ld\n",
                        stream->id, stream->buffer_cycle, position);
                stream->warn_count++;
        }
+
+       return true;
 }
 
 
@@ -167,7 +171,7 @@
                                                        "%08lx/%08lx\n", cad, 
response, responseFlags);
                                                continue;
                                        }
-                               
+
                                        if ((responseFlags & 
RESPONSE_FLAGS_UNSOLICITED) != 0) {
                                                dprintf("hda: Unsolicited 
response: %08lx/%08lx\n",
                                                        response, 
responseFlags);
@@ -211,8 +215,10 @@
                for (uint32 index = 0; index < HDA_MAX_STREAMS; index++) {
                        if ((intrStatus & (1 << index)) != 0) {
                                if (controller->streams[index]) {
-                                       stream_handle_interrupt(controller,
-                                               controller->streams[index]);
+                                       if (stream_handle_interrupt(controller,
+                                                       
controller->streams[index])) {
+                                               handled = B_INVOKE_SCHEDULER;
+                                       }
                                } else {
                                        dprintf("hda: Stream interrupt for 
unconfigured stream "
                                                "%ld!\n", index);
@@ -296,11 +302,11 @@
        // Wait for codecs to finish their own reset (apparently needs more
        // time than documented in the specs)
        snooze(1000);
-       
+
        // Enable unsolicited responses
        control = controller->Read32(HDAC_GLOBAL_CONTROL);
        controller->Write32(HDAC_GLOBAL_CONTROL, control | 
GLOBAL_CONTROL_UNSOLICITED);
-       
+
        return B_OK;
 }
 
@@ -488,7 +494,7 @@
 hda_stream_start(hda_controller* controller, hda_stream* stream)
 {
        dprintf("hda_stream_start() offset %lx\n", stream->offset);
-       
+
        controller->Write32(HDAC_INTR_CONTROL, 
controller->Read32(HDAC_INTR_CONTROL)
                | (1 << (stream->offset / HDAC_STREAM_SIZE)));
        stream->Write8(HDAC_STREAM_CONTROL0, stream->Read8(HDAC_STREAM_CONTROL0)
@@ -577,12 +583,12 @@
                        else if (stream->sample_size > 2)
                                offset = 4;
                } else {
-                       offset = 11;    
+                       offset = 11;
                }
                offset *= 64;
                offset = ALIGN(offset, 128);
        }
-       
+
        /* Calculate size of buffer (aligned to 128 bytes) */
        uint32 bufferSize = stream->sample_size * stream->num_channels
                * stream->buffer_length;
@@ -659,7 +665,7 @@
        }
 
        /* Setup buffer descriptor list (BDL) entries */
-       for (uint32 index = 0; index < stream->num_buffers; index++, 
+       for (uint32 index = 0; index < stream->num_buffers; index++,
                bufferDescriptors++) {
                bufferDescriptors->lower = stream->physical_buffers[index] + 
offset;
                bufferDescriptors->upper = 0;
@@ -689,7 +695,7 @@
                stream->controller->Read32(HDAC_DMA_POSITION_BASE_LOWER)
                | DMA_POSITION_ENABLED);
 
-       dprintf("hda: stream: %ld fifo size: %d num_io_widgets: %ld\n", 
stream->id, 
+       dprintf("hda: stream: %ld fifo size: %d num_io_widgets: %ld\n", 
stream->id,
                stream->Read16(HDAC_STREAM_FIFO_SIZE), stream->num_io_widgets);
        dprintf("hda: widgets: ");
 
@@ -710,7 +716,7 @@
                dprintf("%ld ", stream->io_widgets[i]);
        }
        dprintf("\n");
-       
+
        snooze(1000);
        return B_OK;
 }
@@ -880,7 +886,7 @@
                        break;
                }
        }
-       
+
        controller->buffer_ready_sem = create_sem(0, "hda_buffer_sem");
        if (controller->buffer_ready_sem < B_OK) {
                dprintf("hda: failed to create semaphore\n");
@@ -893,7 +899,7 @@
 
        dprintf("hda: no active codec\n");
        status = ENODEV;
-       
+
        delete_sem(controller->buffer_ready_sem);
 
 corb_rirb_failed:
@@ -940,7 +946,7 @@
 
        /* Stop all audio streams */
        hda_hw_stop(controller);
-       
+
        if (controller->buffer_ready_sem >= B_OK) {
                delete_sem(controller->buffer_ready_sem);
                controller->buffer_ready_sem = B_ERROR;


Other related posts:

  • » [haiku-commits] r34633 - haiku/trunk/src/add-ons/kernel/drivers/audio/hda - ingo_weinhold