* 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:
@@ -52,17 +52,17 @@ enum {
|
|||||||
STREAM_RECORD
|
STREAM_RECORD
|
||||||
};
|
};
|
||||||
|
|
||||||
/* hda_stream_info
|
/* hda_stream
|
||||||
*
|
*
|
||||||
* This structure describes a single stream of audio data,
|
* This structure describes a single stream of audio data,
|
||||||
* which is can have multiple channels (for stereo or better).
|
* which is can have multiple channels (for stereo or better).
|
||||||
*/
|
*/
|
||||||
|
typedef struct hda_stream {
|
||||||
typedef struct hda_stream_info {
|
|
||||||
uint32 id; /* HDA controller stream # */
|
uint32 id; /* HDA controller stream # */
|
||||||
uint32 off; /* HDA I/O/B descriptor offset */
|
uint32 off; /* HDA I/O/B descriptor offset */
|
||||||
bool running; /* Is this stream active? */
|
bool running; /* Is this stream active? */
|
||||||
spinlock lock; /* Write lock */
|
spinlock lock; /* Write lock */
|
||||||
|
uint32 type;
|
||||||
|
|
||||||
uint32 pin_widget; /* PIN Widget ID */
|
uint32 pin_widget; /* PIN Widget ID */
|
||||||
uint32 io_widget; /* Input/Output Converter Widget ID */
|
uint32 io_widget; /* Input/Output Converter Widget ID */
|
||||||
|
|||||||
@@ -35,21 +35,19 @@ hda_stream_new(hda_controller* controller, int type)
|
|||||||
if (stream == NULL)
|
if (stream == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
stream->buffer_ready_sem = B_ERROR;
|
||||||
stream->buffer_area = B_ERROR;
|
stream->buffer_area = B_ERROR;
|
||||||
stream->buffer_descriptors_area = B_ERROR;
|
stream->buffer_descriptors_area = B_ERROR;
|
||||||
|
stream->type = type;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case STREAM_PLAYBACK:
|
case STREAM_PLAYBACK:
|
||||||
stream->buffer_ready_sem = create_sem(0, "hda_playback_sem");
|
|
||||||
stream->id = 1;
|
stream->id = 1;
|
||||||
stream->off = (controller->num_input_streams * HDAC_SDSIZE);
|
stream->off = (controller->num_input_streams * HDAC_SDSIZE);
|
||||||
controller->streams[controller->num_input_streams] = stream;
|
controller->streams[controller->num_input_streams] = stream;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STREAM_RECORD:
|
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->id = 2;
|
||||||
stream->off = 0;
|
stream->off = 0;
|
||||||
controller->streams[0] = stream;
|
controller->streams[0] = stream;
|
||||||
@@ -69,6 +67,11 @@ hda_stream_new(hda_controller* controller, int type)
|
|||||||
status_t
|
status_t
|
||||||
hda_stream_start(hda_controller* controller, hda_stream* stream)
|
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;
|
OREG8(controller, stream->off, CTL0) |= CTL0_RUN;
|
||||||
|
|
||||||
while (!(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);
|
snooze(1);
|
||||||
|
|
||||||
stream->running = false;
|
stream->running = false;
|
||||||
|
delete_sem(stream->buffer_ready_sem);
|
||||||
|
stream->buffer_ready_sem = -1;
|
||||||
|
|
||||||
return B_OK;
|
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,
|
dprintf("%s(%s): Allocated %ld bytes for %ld BDLEs\n", __func__, desc,
|
||||||
alloc, stream->num_buffers);
|
alloc, stream->num_buffers);
|
||||||
|
|
||||||
/* Setup BDL entries */
|
/* Setup buffer descriptor list (BDL) entries */
|
||||||
for (index = 0; index < stream->num_buffers; index++, bufferDescriptors++) {
|
for (index = 0; index < stream->num_buffers; index++, bufferDescriptors++) {
|
||||||
bufferDescriptors->address = stream->physical_buffers[index];
|
bufferDescriptors->address = stream->physical_buffers[index];
|
||||||
bufferDescriptors->length = bufferSize;
|
bufferDescriptors->length = bufferSize;
|
||||||
bufferDescriptors->ioc = 1;
|
bufferDescriptors->ioc = 1;
|
||||||
|
// we want an interrupt after every buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configure stream registers */
|
/* Configure stream registers */
|
||||||
@@ -502,7 +508,7 @@ hda_hw_corb_rirb_init(hda_controller* controller)
|
|||||||
/* NOTE: See HDA011 for corrected procedure! */
|
/* NOTE: See HDA011 for corrected procedure! */
|
||||||
REG16(controller, CORBRP) = CORBRP_RST;
|
REG16(controller, CORBRP) = CORBRP_RST;
|
||||||
do {
|
do {
|
||||||
snooze(10);
|
spin(10);
|
||||||
} while ( !(REG16(controller, CORBRP) & CORBRP_RST) );
|
} while ( !(REG16(controller, CORBRP) & CORBRP_RST) );
|
||||||
REG16(controller, CORBRP) = 0;
|
REG16(controller, CORBRP) = 0;
|
||||||
|
|
||||||
@@ -631,10 +637,11 @@ hda_hw_stop(hda_controller* controller)
|
|||||||
int index;
|
int index;
|
||||||
|
|
||||||
/* Stop all audio streams */
|
/* 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)
|
if (controller->streams[index] && controller->streams[index]->running)
|
||||||
hda_stream_stop(controller, controller->streams[index]);
|
hda_stream_stop(controller, controller->streams[index]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Free resources */
|
/*! Free resources */
|
||||||
|
|||||||
@@ -140,6 +140,13 @@ get_global_format(hda_audio_group* audioGroup, multi_format_info* data)
|
|||||||
static status_t
|
static status_t
|
||||||
set_global_format(hda_audio_group* audioGroup, multi_format_info* data)
|
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_format = data->output.format;
|
||||||
audioGroup->playback_stream->sample_rate = data->output.rate;
|
audioGroup->playback_stream->sample_rate = data->output.rate;
|
||||||
audioGroup->playback_stream->sample_size = format2size(
|
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
|
static status_t
|
||||||
get_buffers(hda_audio_group* audioGroup, multi_buffer_list* data)
|
get_buffers(hda_audio_group* audioGroup, multi_buffer_list* data)
|
||||||
{
|
{
|
||||||
uint32 playback_sample_size = audioGroup->playback_stream->sample_size;
|
uint32 playbackSampleSize = audioGroup->playback_stream->sample_size;
|
||||||
uint32 record_sample_size = audioGroup->record_stream->sample_size;
|
uint32 recordSampleSize = audioGroup->record_stream->sample_size;
|
||||||
uint32 cidx, bidx;
|
uint32 cidx, bidx;
|
||||||
status_t status;
|
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++) {
|
for (cidx = 0; cidx < data->return_playback_channels; cidx++) {
|
||||||
data->playback_buffers[bidx][cidx].base
|
data->playback_buffers[bidx][cidx].base
|
||||||
= audioGroup->playback_stream->buffers[bidx]
|
= audioGroup->playback_stream->buffers[bidx]
|
||||||
+ (playback_sample_size * cidx);
|
+ playbackSampleSize * cidx;
|
||||||
data->playback_buffers[bidx][cidx].stride
|
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++) {
|
for (cidx = 0; cidx < data->return_record_channels; cidx++) {
|
||||||
data->record_buffers[bidx][cidx].base
|
data->record_buffers[bidx][cidx].base
|
||||||
= audioGroup->record_stream->buffers[bidx]
|
= audioGroup->record_stream->buffers[bidx]
|
||||||
+ (record_sample_size * cidx);
|
+ recordSampleSize * cidx;
|
||||||
data->record_buffers[bidx][cidx].stride
|
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->playback_stream);
|
||||||
//hda_stream_stop(audioGroup->codec->controller, audioGroup->record_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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user