Some minor fixes; lots of debugging output still in there; not perfect yet
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23404 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -74,6 +74,7 @@ void
|
||||
uninit_driver (void)
|
||||
{
|
||||
long i;
|
||||
dprintf("IRA: %s\n", __func__);
|
||||
for (i=0; i < num_cards; i++) {
|
||||
free((void*)cards[i].devfs_path);
|
||||
cards[i].devfs_path = NULL;
|
||||
@@ -91,6 +92,7 @@ publish_devices(void)
|
||||
static const char* devs[MAXCARDS+1];
|
||||
long i;
|
||||
|
||||
dprintf("IRA: %s\n", __func__);
|
||||
for (i=0; i < num_cards; i++)
|
||||
devs[i] = cards[i].devfs_path;
|
||||
|
||||
@@ -102,5 +104,6 @@ publish_devices(void)
|
||||
device_hooks*
|
||||
find_device(const char* name)
|
||||
{
|
||||
dprintf("IRA: %s\n", __func__);
|
||||
return &driver_hooks;
|
||||
}
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
#define MAXCARDS 4
|
||||
|
||||
/* values for the class_sub field for class_base = 0x04 (multimedia device) */
|
||||
#define PCI_hd_audio 3
|
||||
#define PCI_hd_audio 3
|
||||
|
||||
#define HDA_MAXAFGS 15
|
||||
#define HDA_MAXAFGS 15
|
||||
#define HDA_MAXCODECS 15
|
||||
#define HDA_MAXSTREAMS 16
|
||||
#define MAX_CODEC_RESPONSES 10
|
||||
#define MAXINPUTS 32
|
||||
#define MAXINPUTS 32
|
||||
|
||||
/* FIXME: Find out why we need so much! */
|
||||
#define DEFAULT_FRAMESPERBUF 4096
|
||||
@@ -52,31 +52,33 @@ enum {
|
||||
*/
|
||||
|
||||
typedef struct hda_stream_info_s {
|
||||
uint32 id; /* HDA controller stream # */
|
||||
uint32 off; /* HDA I/O/B descriptor offset */
|
||||
bool running; /* Is this stream active? */
|
||||
spinlock lock; /* Write lock */
|
||||
|
||||
uint32 pin_wid; /* PIN Widget ID */
|
||||
uint32 io_wid; /* Input/Output Converter Widget ID */
|
||||
uint32 id; /* HDA controller stream # */
|
||||
uint32 off; /* HDA I/O/B descriptor offset */
|
||||
bool running; /* Is this stream active? */
|
||||
spinlock lock; /* Write lock */
|
||||
|
||||
uint32 pin_wid; /* PIN Widget ID */
|
||||
uint32 io_wid; /* Input/Output Converter Widget ID */
|
||||
|
||||
uint32 samplerate;
|
||||
uint32 sampleformat;
|
||||
|
||||
|
||||
uint32 num_buffers;
|
||||
uint32 num_channels;
|
||||
uint32 buffer_length; /* size of buffer in samples */
|
||||
uint32 sample_size;
|
||||
void* buffers[STRMAXBUF]; /* Virtual addresses for buffer */
|
||||
uint32 buffers_pa[STRMAXBUF]; /* Physical addresses for buffer */
|
||||
uint32 buffers_pa[STRMAXBUF]; /* Physical addresses for buffer */
|
||||
sem_id buffer_ready_sem;
|
||||
bigtime_t real_time;
|
||||
uint32 frames_count;
|
||||
uint32 buffer_cycle;
|
||||
|
||||
uint32 rate, bps; /* Samplerate & bits per sample */
|
||||
|
||||
area_id buffer_area;
|
||||
area_id bdl_area;
|
||||
uint32 bdl_pa; /* BDL physical address */
|
||||
uint32 bdl_pa; /* BDL physical address */
|
||||
} hda_stream;
|
||||
|
||||
/* hda_afg
|
||||
@@ -96,12 +98,12 @@ struct hda_afg_s {
|
||||
|
||||
|
||||
uint32 root_nid,
|
||||
wid_start,
|
||||
wid_count;
|
||||
wid_start,
|
||||
wid_count;
|
||||
|
||||
uint32 deffmts,
|
||||
defrates,
|
||||
defpm;
|
||||
defrates,
|
||||
defpm;
|
||||
|
||||
struct {
|
||||
uint32 num_inputs;
|
||||
@@ -124,8 +126,8 @@ struct hda_afg_s {
|
||||
struct {
|
||||
} mixer;
|
||||
struct {
|
||||
uint32 output;
|
||||
uint32 input;
|
||||
uint32 output;
|
||||
uint32 input;
|
||||
pin_dev_type device;
|
||||
} pin;
|
||||
} d;
|
||||
|
||||
@@ -74,8 +74,8 @@ hda_widget_get_stream_support(hda_codec* codec, uint32 nid, uint32* fmts, uint32
|
||||
if (resp[1] & (1<<20)) *fmts |= B_FMT_32BIT;
|
||||
}
|
||||
|
||||
if (resp[0] & (1 << 1)) *fmts |= B_FMT_FLOAT;
|
||||
if (resp[0] & (1 << 2)) /* Sort out how to handle AC3 */;
|
||||
//FIXME: if (resp[0] & (1 << 1)) *fmts |= B_FMT_FLOAT;
|
||||
//FIXME: if (resp[0] & (1 << 2)) /* Sort out how to handle AC3 */;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -147,7 +147,17 @@ hda_codec_parse_afg(hda_afg* afg)
|
||||
|
||||
off = 0;
|
||||
if (resp[0] & (1 << 11)) off += sprintf(buf+off, "[L-R Swap] ");
|
||||
if (resp[0] & (1 << 10)) off += sprintf(buf+off, "[Power] ");
|
||||
if (resp[0] & (1 << 10)) {
|
||||
corb_t verb;
|
||||
uint32 resp;
|
||||
|
||||
off += sprintf(buf+off, "[Power] ");
|
||||
|
||||
/* We support power; switch us on! */
|
||||
verb = MAKE_VERB(afg->codec->addr,wid,VID_SET_POWERSTATE,0);
|
||||
hda_send_verbs(afg->codec, &verb, &resp, 1);
|
||||
}
|
||||
|
||||
if (resp[0] & (1 << 9)) off += sprintf(buf+off, "[Digital] ");
|
||||
if (resp[0] & (1 << 7)) off += sprintf(buf+off, "[Unsol Capable] ");
|
||||
if (resp[0] & (1 << 6)) off += sprintf(buf+off, "[Proc Widget] ");
|
||||
@@ -354,20 +364,16 @@ hda_codec_afg_new(hda_codec* codec, uint32 afg_nid)
|
||||
we cannot find any output Pin Widgets */
|
||||
rc = ENODEV;
|
||||
|
||||
dprintf("%s: Scanning all %ld widgets for outputs/inputs....\n",
|
||||
__func__, afg->wid_count);
|
||||
|
||||
/* Try to locate all input/output channels */
|
||||
for (idx=0; idx < afg->wid_count; idx++) {
|
||||
uint32 output_wid = 0, input_wid = 0;
|
||||
int32 iidx;
|
||||
|
||||
if (afg->widgets[idx].type == WT_PIN_COMPLEX && afg->widgets[idx].d.pin.output) {
|
||||
if (afg->widgets[idx].d.pin.device != PIN_DEV_HP_OUT &&
|
||||
afg->widgets[idx].d.pin.device != PIN_DEV_SPEAKER &&
|
||||
afg->widgets[idx].d.pin.device != PIN_DEV_LINE_OUT)
|
||||
continue;
|
||||
|
||||
if (afg->playback_stream == NULL && afg->widgets[idx].type == WT_PIN_COMPLEX && afg->widgets[idx].d.pin.output) {
|
||||
if (afg->widgets[idx].d.pin.device == PIN_DEV_HP_OUT ||
|
||||
afg->widgets[idx].d.pin.device == PIN_DEV_SPEAKER ||
|
||||
afg->widgets[idx].d.pin.device == PIN_DEV_LINE_OUT)
|
||||
{
|
||||
iidx = afg->widgets[idx].active_input;
|
||||
if (iidx != -1) {
|
||||
output_wid = hda_codec_afg_find_path(afg, afg->widgets[idx].inputs[iidx], WT_AUDIO_OUTPUT, 0);
|
||||
@@ -385,7 +391,7 @@ hda_codec_afg_new(hda_codec* codec, uint32 afg_nid)
|
||||
|
||||
if (output_wid) {
|
||||
if (!afg->playback_stream) {
|
||||
corb_t verb;
|
||||
corb_t verb[2];
|
||||
|
||||
/* Setup playback/record streams for Multi Audio API */
|
||||
afg->playback_stream = hda_stream_new(afg->codec->ctrlr, STRM_PLAYBACK);
|
||||
@@ -394,16 +400,19 @@ hda_codec_afg_new(hda_codec* codec, uint32 afg_nid)
|
||||
afg->playback_stream->pin_wid = idx + afg->wid_start;
|
||||
afg->playback_stream->io_wid = output_wid;
|
||||
|
||||
/* FIXME: Force Pin Widget to unmute */
|
||||
verb = MAKE_VERB(codec->addr, afg->playback_stream->pin_wid,
|
||||
/* FIXME: Force Pin Widget to unmute; enable hp/output */
|
||||
verb[0] = MAKE_VERB(codec->addr, afg->playback_stream->pin_wid,
|
||||
VID_SET_AMPGAINMUTE, (1 << 15) | (1 << 13) | (1 << 12));
|
||||
hda_send_verbs(codec, &verb, NULL, 1);
|
||||
verb[1] = MAKE_VERB(codec->addr, afg->playback_stream->pin_wid,
|
||||
VID_SET_PINWCTRL, (1 << 7) | (1 << 6));
|
||||
hda_send_verbs(codec, verb, NULL, 2);
|
||||
|
||||
dprintf("%s: Found output PIN (%s) connected to output CONV wid:%ld\n",
|
||||
__func__, defdev[afg->widgets[idx].d.pin.device], output_wid);
|
||||
}
|
||||
|
||||
dprintf("%s: Found output PIN (%s) connected to output CONV wid:%ld\n",
|
||||
__func__, defdev[afg->widgets[idx].d.pin.device], output_wid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (afg->widgets[idx].type == WT_AUDIO_INPUT) {
|
||||
iidx = afg->widgets[idx].active_input;
|
||||
|
||||
@@ -183,38 +183,41 @@ hda_stream_setup_buffers(hda_afg* afg, hda_stream* s, const char* desc)
|
||||
|
||||
dprintf("%s(%s): Allocated %ld bytes for %ld BDLEs\n", __func__, desc,
|
||||
alloc, s->num_buffers);
|
||||
|
||||
|
||||
/* Setup BDL entries */
|
||||
for (idx=0; idx < s->num_buffers; idx++, bdl++) {
|
||||
bdl->address = buffer_pa + (idx*buffer_size);
|
||||
bdl->length = s->sample_size * s->num_channels * s->buffer_length;
|
||||
bdl->address = s->buffers_pa[idx];
|
||||
bdl->length = buffer_size;
|
||||
bdl->ioc = 1;
|
||||
}
|
||||
|
||||
/* Configure stream registers */
|
||||
wfmt = s->num_channels -1;
|
||||
switch(s->sampleformat) {
|
||||
case B_FMT_8BIT_S: wfmt |= (0 << 4); break;
|
||||
case B_FMT_16BIT: wfmt |= (1 << 4); break;
|
||||
case B_FMT_24BIT: wfmt |= (3 << 4); break;
|
||||
case B_FMT_32BIT: wfmt |= (4 << 4); break;
|
||||
default: dprintf("%s: Invalid sample format: 0x%lx\n", __func__, s->sampleformat); break;
|
||||
case B_FMT_8BIT_S: wfmt |= (0 << 4); s->bps = 8; break;
|
||||
case B_FMT_16BIT: wfmt |= (1 << 4); s->bps = 16; break;
|
||||
case B_FMT_24BIT: wfmt |= (3 << 4); s->bps = 24; break;
|
||||
case B_FMT_32BIT: wfmt |= (4 << 4); s->bps = 32; break;
|
||||
default: dprintf("%s: Invalid sample format: 0x%lx\n", __func__, s->sampleformat); break;
|
||||
}
|
||||
|
||||
switch(s->samplerate) {
|
||||
case B_SR_8000: wfmt |= (7 << 8); break;
|
||||
case B_SR_11025: wfmt |= (67 << 8); break;
|
||||
case B_SR_16000: wfmt |= (2 << 8); break;
|
||||
case B_SR_22050: wfmt |= (65 << 8); break;
|
||||
case B_SR_32000: wfmt |= (10 << 8); break;
|
||||
case B_SR_44100: wfmt |= (64 << 8); break;
|
||||
case B_SR_48000: wfmt |= (0 << 8); break;
|
||||
case B_SR_88200: wfmt |= (72 << 8); break;
|
||||
case B_SR_96000: wfmt |= (8 << 8); break;
|
||||
case B_SR_176400: wfmt |= (88 << 8); break;
|
||||
case B_SR_192000: wfmt |= (24 << 8); break;
|
||||
default: dprintf("%s: Invalid sample rate: 0x%lx\n", __func__, s->samplerate); break;
|
||||
case B_SR_8000: wfmt |= (0 << 14) | (0 << 11) | (5 << 8); s->rate=8000; break;
|
||||
case B_SR_11025: wfmt |= (1 << 14) | (0 << 11) | (3 << 8); s->rate=11025; break;
|
||||
case B_SR_16000: wfmt |= (0 << 14) | (0 << 11) | (2 << 8); s->rate=16000; break;
|
||||
case B_SR_22050: wfmt |= (1 << 14) | (0 << 11) | (1 << 8); s->rate=22050; break;
|
||||
case B_SR_32000: wfmt |= (0 << 14) | (1 << 11) | (2 << 8); s->rate=32000; break;
|
||||
case B_SR_44100: wfmt |= (1 << 14) | (0 << 11) | (0 << 8); s->rate=44100; break;
|
||||
case B_SR_48000: wfmt |= (0 << 14) | (0 << 11) | (0 << 8); s->rate=48000; break;
|
||||
case B_SR_88200: wfmt |= (1 << 14) | (1 << 11) | (0 << 8); s->rate=88200; break;
|
||||
case B_SR_96000: wfmt |= (0 << 14) | (2 << 11) | (0 << 8); s->rate=96000; break;
|
||||
case B_SR_176400: wfmt |= (1 << 14) | (3 << 11) | (0 << 8); s->rate=176400; break;
|
||||
case B_SR_192000: wfmt |= (0 << 14) | (3 << 11) | (0 << 8); s->rate=192000; break;
|
||||
default: dprintf("%s: Invalid sample rate: 0x%lx\n", __func__, s->samplerate); break;
|
||||
}
|
||||
|
||||
dprintf("IRA: %s: setup stream %ld: SR=%ld, SF=%ld\n", __func__, s->id, s->rate, s->bps);
|
||||
|
||||
OREG16(afg->codec->ctrlr,s->off,FMT) = wfmt;
|
||||
OREG32(afg->codec->ctrlr,s->off,BDPL) = s->bdl_pa;
|
||||
OREG32(afg->codec->ctrlr,s->off,BDPU) = 0;
|
||||
|
||||
@@ -173,7 +173,7 @@ get_buffers(hda_afg* afg, multi_buffer_list* data)
|
||||
|
||||
/* ... from here on, we can assume again that a reasonable request is being made */
|
||||
|
||||
data->flags = 0;
|
||||
data->flags = B_MULTI_BUFFER_PLAYBACK;
|
||||
|
||||
/* Copy the requested settings into the streams */
|
||||
afg->playback_stream->num_buffers = data->request_playback_buffers;
|
||||
@@ -218,6 +218,8 @@ get_buffers(hda_afg* afg, multi_buffer_list* data)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* playback_buffer_cycle is the buffer we want to have played */
|
||||
|
||||
static status_t
|
||||
buffer_exchange(hda_afg* afg, multi_buffer_info* data)
|
||||
{
|
||||
@@ -258,7 +260,7 @@ static status_t
|
||||
buffer_force_stop(hda_afg* afg)
|
||||
{
|
||||
hda_stream_stop(afg->codec->ctrlr, afg->playback_stream);
|
||||
hda_stream_stop(afg->codec->ctrlr, afg->record_stream);
|
||||
//hda_stream_stop(afg->codec->ctrlr, afg->record_stream);
|
||||
|
||||
delete_sem(afg->playback_stream->buffer_ready_sem);
|
||||
// delete_sem(afg->record_stream->buffer_ready_sem);
|
||||
|
||||
Reference in New Issue
Block a user