* 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
This commit is contained in:
Axel Dörfler 2008-02-25 19:34:37 +00:00
parent 1cf41b6de1
commit 629ab634f5
3 changed files with 30 additions and 19 deletions

View File

@ -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 */

View File

@ -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]);
}
}

View File

@ -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;
}