From 629ab634f57a2322639b423f0b21dde156fae3b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 25 Feb 2008 19:34:37 +0000 Subject: [PATCH] * Playback can now be restarted after B_MULTI_BUFFER_FORCE_STOP again; the hda_stream::buffer_ready_sem was deleted but not recreated again. Moved its maintenance to hda_stream_{start|stop}(). * Replaced snooze(10) with spin(10) because that's probably what's wanted here. * Added hda_stream::type field. * Minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24122 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/drivers/audio/hda/driver.h | 6 ++--- .../kernel/drivers/audio/hda/hda_controller.c | 21 ++++++++++++------ .../drivers/audio/hda/hda_multi_audio.c | 22 +++++++++++-------- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/add-ons/kernel/drivers/audio/hda/driver.h b/src/add-ons/kernel/drivers/audio/hda/driver.h index 642659fdb5..192cdf1030 100644 --- a/src/add-ons/kernel/drivers/audio/hda/driver.h +++ b/src/add-ons/kernel/drivers/audio/hda/driver.h @@ -52,17 +52,17 @@ enum { STREAM_RECORD }; -/* hda_stream_info +/* hda_stream * * This structure describes a single stream of audio data, * which is can have multiple channels (for stereo or better). */ - -typedef struct hda_stream_info { +typedef struct hda_stream { uint32 id; /* HDA controller stream # */ uint32 off; /* HDA I/O/B descriptor offset */ bool running; /* Is this stream active? */ spinlock lock; /* Write lock */ + uint32 type; uint32 pin_widget; /* PIN Widget ID */ uint32 io_widget; /* Input/Output Converter Widget ID */ diff --git a/src/add-ons/kernel/drivers/audio/hda/hda_controller.c b/src/add-ons/kernel/drivers/audio/hda/hda_controller.c index 1354f0bb14..5579a9096e 100644 --- a/src/add-ons/kernel/drivers/audio/hda/hda_controller.c +++ b/src/add-ons/kernel/drivers/audio/hda/hda_controller.c @@ -35,21 +35,19 @@ hda_stream_new(hda_controller* controller, int type) if (stream == NULL) return NULL; + stream->buffer_ready_sem = B_ERROR; stream->buffer_area = B_ERROR; stream->buffer_descriptors_area = B_ERROR; + stream->type = type; switch (type) { case STREAM_PLAYBACK: - stream->buffer_ready_sem = create_sem(0, "hda_playback_sem"); stream->id = 1; stream->off = (controller->num_input_streams * HDAC_SDSIZE); controller->streams[controller->num_input_streams] = stream; break; case STREAM_RECORD: - stream->buffer_area = B_ERROR; - stream->buffer_descriptors_area = B_ERROR; - stream->buffer_ready_sem = create_sem(0, "hda_record_sem"); stream->id = 2; stream->off = 0; controller->streams[0] = stream; @@ -69,6 +67,11 @@ hda_stream_new(hda_controller* controller, int type) status_t hda_stream_start(hda_controller* controller, hda_stream* stream) { + stream->buffer_ready_sem = create_sem(0, + stream->type == STREAM_PLAYBACK ? "hda_playback_sem" : "hda_record_sem"); + if (stream->buffer_ready_sem < B_OK) + return stream->buffer_ready_sem; + OREG8(controller, stream->off, CTL0) |= CTL0_RUN; while (!(OREG8(controller, stream->off, CTL0) & CTL0_RUN)) @@ -121,6 +124,8 @@ hda_stream_stop(hda_controller* controller, hda_stream* stream) snooze(1); stream->running = false; + delete_sem(stream->buffer_ready_sem); + stream->buffer_ready_sem = -1; return B_OK; } @@ -211,11 +216,12 @@ dprintf("HDA: sample size %ld, num channels %ld, buffer length %ld ************* dprintf("%s(%s): Allocated %ld bytes for %ld BDLEs\n", __func__, desc, alloc, stream->num_buffers); - /* Setup BDL entries */ + /* Setup buffer descriptor list (BDL) entries */ for (index = 0; index < stream->num_buffers; index++, bufferDescriptors++) { bufferDescriptors->address = stream->physical_buffers[index]; bufferDescriptors->length = bufferSize; bufferDescriptors->ioc = 1; + // we want an interrupt after every buffer } /* Configure stream registers */ @@ -502,7 +508,7 @@ hda_hw_corb_rirb_init(hda_controller* controller) /* NOTE: See HDA011 for corrected procedure! */ REG16(controller, CORBRP) = CORBRP_RST; do { - snooze(10); + spin(10); } while ( !(REG16(controller, CORBRP) & CORBRP_RST) ); REG16(controller, CORBRP) = 0; @@ -631,9 +637,10 @@ hda_hw_stop(hda_controller* controller) int index; /* Stop all audio streams */ - for (index = 0; index < HDA_MAX_STREAMS; index++) + for (index = 0; index < HDA_MAX_STREAMS; index++) { if (controller->streams[index] && controller->streams[index]->running) hda_stream_stop(controller, controller->streams[index]); + } } diff --git a/src/add-ons/kernel/drivers/audio/hda/hda_multi_audio.c b/src/add-ons/kernel/drivers/audio/hda/hda_multi_audio.c index d456744a83..9a3abfcc2b 100644 --- a/src/add-ons/kernel/drivers/audio/hda/hda_multi_audio.c +++ b/src/add-ons/kernel/drivers/audio/hda/hda_multi_audio.c @@ -140,6 +140,13 @@ get_global_format(hda_audio_group* audioGroup, multi_format_info* data) static status_t set_global_format(hda_audio_group* audioGroup, multi_format_info* data) { + // TODO: it looks like we're not supposed to fail; fix this! +#if 0 + if ((data->output.format & audioGroup->supported_formats) == 0) + || (data->output.rate & audioGroup->supported_rates) == 0) + return B_BAD_VALUE; +#endif + audioGroup->playback_stream->sample_format = data->output.format; audioGroup->playback_stream->sample_rate = data->output.rate; audioGroup->playback_stream->sample_size = format2size( @@ -181,8 +188,8 @@ list_mix_channels(hda_audio_group* audioGroup, multi_mix_channel_info *data) static status_t get_buffers(hda_audio_group* audioGroup, multi_buffer_list* data) { - uint32 playback_sample_size = audioGroup->playback_stream->sample_size; - uint32 record_sample_size = audioGroup->record_stream->sample_size; + uint32 playbackSampleSize = audioGroup->playback_stream->sample_size; + uint32 recordSampleSize = audioGroup->record_stream->sample_size; uint32 cidx, bidx; status_t status; @@ -257,9 +264,9 @@ get_buffers(hda_audio_group* audioGroup, multi_buffer_list* data) for (cidx = 0; cidx < data->return_playback_channels; cidx++) { data->playback_buffers[bidx][cidx].base = audioGroup->playback_stream->buffers[bidx] - + (playback_sample_size * cidx); + + playbackSampleSize * cidx; data->playback_buffers[bidx][cidx].stride - = playback_sample_size * data->return_playback_channels; + = playbackSampleSize * data->return_playback_channels; } } @@ -267,9 +274,9 @@ get_buffers(hda_audio_group* audioGroup, multi_buffer_list* data) for (cidx = 0; cidx < data->return_record_channels; cidx++) { data->record_buffers[bidx][cidx].base = audioGroup->record_stream->buffers[bidx] - + (record_sample_size * cidx); + + recordSampleSize * cidx; data->record_buffers[bidx][cidx].stride - = record_sample_size * data->return_record_channels; + = recordSampleSize * data->return_record_channels; } } @@ -323,9 +330,6 @@ buffer_force_stop(hda_audio_group* audioGroup) hda_stream_stop(audioGroup->codec->controller, audioGroup->playback_stream); //hda_stream_stop(audioGroup->codec->controller, audioGroup->record_stream); - delete_sem(audioGroup->playback_stream->buffer_ready_sem); -// delete_sem(audioGroup->record_stream->buffer_ready_sem); - return B_OK; }