added a settings file for auich

there is now an option for laptops for which no interrupt is available (ie stippi's one) : use_thread
even when use_thread is active, it could be needed to use a higher value for buffer_frames (ie 512)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18406 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval
2006-08-05 20:10:48 +00:00
parent cd270b7da8
commit bc19ead830
5 changed files with 103 additions and 24 deletions
@@ -34,8 +34,10 @@
#include <KernelExport.h>
#include <PCI.h>
#include <string.h>
#include <driver_settings.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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);
}
@@ -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];
@@ -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
@@ -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;
@@ -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);