diff --git a/src/add-ons/kernel/drivers/audio/ac97/auich/auich.c b/src/add-ons/kernel/drivers/audio/ac97/auich/auich.c index cc866e7a1c..ec0ee582b7 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/auich/auich.c +++ b/src/add-ons/kernel/drivers/audio/ac97/auich/auich.c @@ -34,8 +34,10 @@ #include #include -#include +#include #include +#include +#include #include "auich.h" #include "debug.h" #include "config.h" @@ -62,8 +64,18 @@ auich_dev cards[NUM_CARDS]; int32 num_names; char * names[NUM_CARDS*20+1]; +volatile bool int_thread_exit = false; +thread_id int_thread_id = -1; + extern device_hooks multi_hooks; +auich_settings current_settings = { + 48000, // sample rate + 256, // buffer frames + 4, // buffer count + false // use thread +}; + /* The SIS7012 chipset has SR and PICB registers swapped when compared to Intel */ #define GET_REG_PICB(x) (IS_SIS7012(x) ? AUICH_REG_X_SR : AUICH_REG_X_PICB) #define GET_REG_SR(x) (IS_SIS7012(x) ? AUICH_REG_X_PICB : AUICH_REG_X_SR) @@ -397,7 +409,7 @@ auich_int(void *arg) auich_stream *stream = NULL; uint16 sr, sta; - //TRACE(("auich_int(%p)\n", card)); + // TRACE(("auich_int(%p)\n", card)); sta = auich_reg_read_16(&card->config, AUICH_REG_GLOB_STA); if(sta & card->interrupt_mask) { @@ -451,6 +463,21 @@ auich_int(void *arg) return B_UNHANDLED_INTERRUPT; } + +static int32 +auich_int_thread(void *data) +{ + cpu_status status; + while (!int_thread_exit) { + status = disable_interrupts(); + auich_int(data); + restore_interrupts(status); + snooze(1500); + } + return 0; +} + + /* auich driver functions */ static status_t @@ -654,8 +681,13 @@ auich_setup(auich_dev * card) PRINT(("codec description = %s\n",ac97_get_vendor_id_description(&card->config))); PRINT(("codec 3d enhancement = %s\n",ac97_get_3d_stereo_enhancement(&card->config))); - PRINT(("installing interrupt : %lx\n", card->config.irq)); - install_io_interrupt_handler(card->config.irq, auich_int, card, 0); + if (current_settings.use_thread) { + int_thread_id = spawn_kernel_thread(auich_int_thread, "auich interrupt poller", B_REAL_TIME_PRIORITY, card); + resume_thread(int_thread_id); + } else { + PRINT(("installing interrupt : %lx\n", card->config.irq)); + install_io_interrupt_handler(card->config.irq, auich_int, card, 0); + } /*PRINT(("codec master output = %#04x\n",auich_codec_read(&card->config, 0x02))); PRINT(("codec aux output = %#04x\n",auich_codec_read(&card->config, 0x04))); @@ -703,12 +735,37 @@ status_t init_driver(void) { int ix=0; + void *settings_handle; pci_info info; num_cards = 0; PRINT(("init_driver()\n")); load_driver_symbols("auich"); + + // get driver settings + settings_handle = load_driver_settings ("auich.settings"); + if (settings_handle != NULL) { + const char *item; + char *end; + uint32 value; + + item = get_driver_parameter (settings_handle, "sample_rate", "48000", "48000"); + value = strtoul (item, &end, 0); + if (*end == '\0') current_settings.sample_rate = value; + + item = get_driver_parameter (settings_handle, "buffer_frames", "256", "256"); + value = strtoul (item, &end, 0); + if (*end == '\0') current_settings.buffer_frames = value; + + item = get_driver_parameter (settings_handle, "buffer_count", "4", "4"); + value = strtoul (item, &end, 0); + if (*end == '\0') current_settings.buffer_count = value; + + current_settings.use_thread = get_driver_boolean_parameter (settings_handle, "use_thread", false, false); + + unload_driver_settings (settings_handle); + } if (get_module(pci_name, (module_info **) &pci)) return ENOSYS; @@ -775,8 +832,13 @@ auich_shutdown(auich_dev *card) PRINT(("shutdown(%p)\n", card)); card->interrupt_mask = 0; - remove_io_interrupt_handler(card->config.irq, auich_int, card); - + if (current_settings.use_thread) { + status_t exit_value; + int_thread_exit = true; + wait_for_thread(int_thread_id, &exit_value); + } else + remove_io_interrupt_handler(card->config.irq, auich_int, card); + unmap_io_memory(&card->config); } diff --git a/src/add-ons/kernel/drivers/audio/ac97/auich/auich.h b/src/add-ons/kernel/drivers/audio/ac97/auich/auich.h index a72a4dd43a..367fbd7fdd 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/auich/auich.h +++ b/src/add-ons/kernel/drivers/audio/ac97/auich/auich.h @@ -168,6 +168,16 @@ typedef struct _auich_dev { multi_dev multi; } auich_dev; + +typedef struct { + uint32 sample_rate; + uint32 buffer_frames; + int32 buffer_count; + bool use_thread; +} auich_settings; + +extern auich_settings current_settings; + extern int32 num_cards; extern auich_dev cards[NUM_CARDS]; diff --git a/src/add-ons/kernel/drivers/audio/ac97/auich/auich.settings b/src/add-ons/kernel/drivers/audio/ac97/auich/auich.settings new file mode 100644 index 0000000000..4de145552c --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/ac97/auich/auich.settings @@ -0,0 +1,10 @@ +# Settings file for the auich driver +# +# This file should be moved to the directory +# ~/config/settings/kernel/drivers/ +# + +#sample_rate 48000 +#buffer_frames 256 +#buffer_count 4 +#use_thread false diff --git a/src/add-ons/kernel/drivers/audio/ac97/auich/multi.c b/src/add-ons/kernel/drivers/audio/ac97/auich/multi.c index c203a2e192..86b3871711 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/auich/multi.c +++ b/src/add-ons/kernel/drivers/audio/ac97/auich/multi.c @@ -766,23 +766,23 @@ auich_get_buffers(auich_dev *card, multi_buffer_list *data) pchannels = card->pstream->channels; rchannels = card->rstream->channels; - if (data->request_playback_buffers < BUFFER_COUNT || + if (data->request_playback_buffers < current_settings.buffer_count || data->request_playback_channels < (pchannels) || - data->request_record_buffers < BUFFER_COUNT || + data->request_record_buffers < current_settings.buffer_count || data->request_record_channels < (rchannels)) { LOG(("not enough channels/buffers\n")); } - ASSERT(BUFFER_COUNT == 2); + ASSERT(current_settings.buffer_count == 2); data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; // XXX ??? // data->flags = 0; - data->return_playback_buffers = BUFFER_COUNT; /* playback_buffers[b][] */ + data->return_playback_buffers = current_settings.buffer_count; /* playback_buffers[b][] */ data->return_playback_channels = pchannels; /* playback_buffers[][c] */ - data->return_playback_buffer_size = BUFFER_FRAMES; /* frames */ + data->return_playback_buffer_size = current_settings.buffer_frames; /* frames */ - bufcount = BUFFER_COUNT; + bufcount = current_settings.buffer_count; if(bufcount > data->request_playback_buffers) bufcount = data->request_playback_buffers; @@ -792,11 +792,11 @@ auich_get_buffers(auich_dev *card, multi_buffer_list *data) &data->playback_buffers[i][j].base, &data->playback_buffers[i][j].stride); - data->return_record_buffers = BUFFER_COUNT; + data->return_record_buffers = current_settings.buffer_count; data->return_record_channels = rchannels; - data->return_record_buffer_size = BUFFER_FRAMES; /* frames */ + data->return_record_buffer_size = current_settings.buffer_frames; /* frames */ - bufcount = BUFFER_COUNT; + bufcount = current_settings.buffer_count; if(bufcount > data->request_record_buffers) bufcount = data->request_record_buffers; @@ -818,7 +818,7 @@ auich_play_inth(void* inthparams) acquire_spinlock(&slock); stream->real_time = system_time(); - stream->frames_count += BUFFER_FRAMES; + stream->frames_count += current_settings.buffer_frames; stream->buffer_cycle = (stream->trigblk + stream->blkmod - 1) % stream->blkmod; stream->update_needed = true; @@ -839,7 +839,7 @@ auich_record_inth(void* inthparams) acquire_spinlock(&slock); stream->real_time = system_time(); - stream->frames_count += BUFFER_FRAMES; + stream->frames_count += current_settings.buffer_frames; stream->buffer_cycle = (stream->trigblk + stream->blkmod - 1) % stream->blkmod; stream->update_needed = true; @@ -1047,15 +1047,15 @@ auich_open(const char *name, uint32 flags, void** cookie) LOG(("stream_new\n")); - card->rstream = auich_stream_new(card, AUICH_USE_RECORD, BUFFER_FRAMES, BUFFER_COUNT); - card->pstream = auich_stream_new(card, AUICH_USE_PLAY, BUFFER_FRAMES, BUFFER_COUNT); + card->rstream = auich_stream_new(card, AUICH_USE_RECORD, current_settings.buffer_frames, current_settings.buffer_count); + card->pstream = auich_stream_new(card, AUICH_USE_PLAY, current_settings.buffer_frames, current_settings.buffer_count); card->buffer_ready_sem = create_sem(0, "pbuffer ready"); LOG(("stream_setaudio\n")); - auich_stream_set_audioparms(card->pstream, 2, true, 48000); - auich_stream_set_audioparms(card->rstream, 2, true, 48000); + auich_stream_set_audioparms(card->pstream, 2, true, current_settings.sample_rate); + auich_stream_set_audioparms(card->rstream, 2, true, current_settings.sample_rate); card->pstream->first_channel = 0; card->rstream->first_channel = 2; diff --git a/src/add-ons/kernel/drivers/audio/ac97/auich/multi.h b/src/add-ons/kernel/drivers/audio/ac97/auich/multi.h index 04d0fd35d1..1d5cb851c8 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/auich/multi.h +++ b/src/add-ons/kernel/drivers/audio/ac97/auich/multi.h @@ -31,9 +31,6 @@ #ifndef _MULTI_H_ #define _MULTI_H_ -#define BUFFER_FRAMES 256 -#define BUFFER_COUNT 4 - typedef struct _multi_mixer_control { struct _multi_dev *multi; void (*get) (void *card, const void *cookie, int32 type, float *values);