Renamed .c to .cpp, and fixed all warnings.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24178 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-02-29 14:54:30 +00:00
parent 105152d1f5
commit 340dd4fe3d
8 changed files with 204 additions and 210 deletions
+5 -5
View File
@@ -5,11 +5,11 @@ SetSubDirSupportedPlatformsBeOSCompatible ;
UsePrivateHeaders media ; UsePrivateHeaders media ;
KernelAddon hda : KernelAddon hda :
driver.c driver.cpp
hooks.c device.cpp
hda_multi_audio.c hda_multi_audio.cpp
hda_controller.c hda_controller.cpp
hda_codec.c hda_codec.cpp
; ;
Package haiku-hda-cvs : Package haiku-hda-cvs :
@@ -14,10 +14,8 @@ static status_t
hda_open(const char *name, uint32 flags, void** cookie) hda_open(const char *name, uint32 flags, void** cookie)
{ {
hda_controller* controller = NULL; hda_controller* controller = NULL;
status_t rc = B_OK;
long i;
for (i = 0; i < gNumCards; i++) { for (uint32 i = 0; i < gNumCards; i++) {
if (strcmp(gCards[i].devfs_path, name) == 0) { if (strcmp(gCards[i].devfs_path, name) == 0) {
controller = &gCards[i]; controller = &gCards[i];
break; break;
@@ -30,11 +28,11 @@ hda_open(const char *name, uint32 flags, void** cookie)
if (controller->opened) if (controller->opened)
return B_BUSY; return B_BUSY;
rc = hda_hw_init(controller); status_t status = hda_hw_init(controller);
if (rc != B_OK) if (status != B_OK)
return rc; return status;
controller->opened++; atomic_add(&controller->opened, 1);
*cookie = controller; *cookie = controller;
return B_OK; return B_OK;
@@ -75,7 +73,7 @@ hda_close(void* cookie)
{ {
hda_controller* controller = (hda_controller*)cookie; hda_controller* controller = (hda_controller*)cookie;
hda_hw_stop(controller); hda_hw_stop(controller);
--controller->opened; atomic_add(&controller->opened, -1);
return B_OK; return B_OK;
} }
@@ -17,7 +17,7 @@ uint32 gNumCards;
pci_module_info* gPci; pci_module_info* gPci;
status_t extern "C" status_t
init_hardware(void) init_hardware(void)
{ {
pci_info info; pci_info info;
@@ -39,7 +39,7 @@ init_hardware(void)
} }
status_t extern "C" status_t
init_driver(void) init_driver(void)
{ {
char path[B_PATH_NAME_LENGTH]; char path[B_PATH_NAME_LENGTH];
@@ -76,13 +76,12 @@ init_driver(void)
} }
void extern "C" void
uninit_driver(void) uninit_driver(void)
{ {
long i;
dprintf("IRA: %s\n", __func__); dprintf("IRA: %s\n", __func__);
for (i = 0; i < gNumCards; i++) { for (uint32 i = 0; i < gNumCards; i++) {
free((void*)gCards[i].devfs_path); free((void*)gCards[i].devfs_path);
gCards[i].devfs_path = NULL; gCards[i].devfs_path = NULL;
} }
@@ -91,15 +90,16 @@ uninit_driver(void)
} }
const char** extern "C" const char**
publish_devices(void) publish_devices(void)
{ {
static const char* devs[MAX_CARDS + 1]; static const char* devs[MAX_CARDS + 1];
long i; uint32 i;
dprintf("IRA: %s\n", __func__); dprintf("IRA: %s\n", __func__);
for (i = 0; i < gNumCards; i++) for (i = 0; i < gNumCards; i++) {
devs[i] = gCards[i].devfs_path; devs[i] = gCards[i].devfs_path;
}
devs[i] = NULL; devs[i] = NULL;
@@ -107,7 +107,7 @@ publish_devices(void)
} }
device_hooks* extern "C" device_hooks*
find_device(const char* name) find_device(const char* name)
{ {
dprintf("IRA: %s\n", __func__); dprintf("IRA: %s\n", __func__);
+72 -80
View File
@@ -40,10 +40,6 @@
/* FIXME: Find out why we need so much! */ /* FIXME: Find out why we need so much! */
#define DEFAULT_FRAMES_PER_BUFFER 4096 #define DEFAULT_FRAMES_PER_BUFFER 4096
typedef struct hda_controller hda_controller;
typedef struct hda_codec hda_codec;
typedef struct hda_audio_group hda_audio_group;
#define STREAM_MAX_BUFFERS 10 #define STREAM_MAX_BUFFERS 10
#define STREAM_MIN_BUFFERS 2 #define STREAM_MIN_BUFFERS 2
@@ -52,12 +48,12 @@ enum {
STREAM_RECORD STREAM_RECORD
}; };
/* hda_stream struct hda_codec;
*
* 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 { struct hda_stream {
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? */
@@ -74,7 +70,7 @@ typedef struct hda_stream {
uint32 num_channels; uint32 num_channels;
uint32 buffer_length; /* size of buffer in samples */ uint32 buffer_length; /* size of buffer in samples */
uint32 sample_size; uint32 sample_size;
void* buffers[STREAM_MAX_BUFFERS]; uint8* buffers[STREAM_MAX_BUFFERS];
/* Virtual addresses for buffer */ /* Virtual addresses for buffer */
uint32 physical_buffers[STREAM_MAX_BUFFERS]; uint32 physical_buffers[STREAM_MAX_BUFFERS];
/* Physical addresses for buffer */ /* Physical addresses for buffer */
@@ -88,68 +84,66 @@ typedef struct hda_stream {
area_id buffer_area; area_id buffer_area;
area_id buffer_descriptors_area; area_id buffer_descriptors_area;
uint32 physical_buffer_descriptors; /* BDL physical address */ uint32 physical_buffer_descriptors; /* BDL physical address */
} hda_stream;
/* hda_audio_group
*
* This structure describes a single Audio Function Group. An afg
* is a group of audio widgets which can be used to configure multiple
* streams of audio either from the HDA Link to an output device (= playback)
* or from an input device to the HDA link (= recording).
*/
struct hda_audio_group {
hda_codec* codec;
/* Multi Audio API data */
hda_stream* playback_stream;
hda_stream* record_stream;
uint32 root_node_id;
uint32 widget_start;
uint32 widget_count;
uint32 supported_formats;
uint32 supported_rates;
uint32 supported_pm;
struct {
uint32 num_inputs;
int32 active_input;
uint32 inputs[MAX_INPUTS];
uint32 flags;
hda_widget_type type;
uint32 pm;
union {
struct {
uint32 formats;
uint32 rates;
} output;
struct {
uint32 formats;
uint32 rates;
} input;
struct {
} mixer;
struct {
uint32 output;
uint32 input;
pin_dev_type device;
} pin;
} d;
} *widgets;
}; };
/* hda_codec struct hda_widget {
* uint32 num_inputs;
* This structure describes a single codec module in the int32 active_input;
* HDA compliant device. This is a discrete component, which uint32 inputs[MAX_INPUTS];
* can contain both Audio Function Groups, Modem Function Groups, uint32 flags;
* and other customized (vendor specific) Function Groups.
* hda_widget_type type;
* NOTE: Atm, only Audio Function Groups are supported. uint32 pm;
*/
union {
struct {
uint32 formats;
uint32 rates;
} output;
struct {
uint32 formats;
uint32 rates;
} input;
struct {
} mixer;
struct {
uint32 output;
uint32 input;
pin_dev_type device;
} pin;
} d;
};
/*! This structure describes a single Audio Function Group. An afg
is a group of audio widgets which can be used to configure multiple
streams of audio either from the HDA Link to an output device (= playback)
or from an input device to the HDA link (= recording).
*/
struct hda_audio_group {
hda_codec* codec;
/* Multi Audio API data */
hda_stream* playback_stream;
hda_stream* record_stream;
uint32 root_node_id;
uint32 widget_start;
uint32 widget_count;
uint32 supported_formats;
uint32 supported_rates;
uint32 supported_pm;
hda_widget* widgets;
};
/*! This structure describes a single codec module in the
HDA compliant device. This is a discrete component, which
can contain both Audio Function Groups, Modem Function Groups,
and other customized (vendor specific) Function Groups.
NOTE: ATM, only Audio Function Groups are supported.
*/
struct hda_codec { struct hda_codec {
uint16 vendor_id; uint16 vendor_id;
uint16 product_id; uint16 product_id;
@@ -167,16 +161,14 @@ struct hda_codec {
struct hda_controller* controller; struct hda_controller* controller;
}; };
/* hda_controller /*! This structure describes a single HDA compliant
* controller. It contains a list of available streams
* This structure describes a single HDA compliant for use by the codecs contained, and the messaging queue
* controller. It contains a list of available streams (verb/response) buffers for communication.
* for use by the codecs contained, and the messaging queue */
* (verb/response) buffers for communication.
*/
struct hda_controller { struct hda_controller {
struct pci_info pci_info; struct pci_info pci_info;
vuint32 opened; vint32 opened;
const char* devfs_path; const char* devfs_path;
area_id regs_area; area_id regs_area;
@@ -222,7 +214,7 @@ status_t hda_hw_init(hda_controller* controller);
void hda_hw_stop(hda_controller* controller); void hda_hw_stop(hda_controller* controller);
void hda_hw_uninit(hda_controller* controller); void hda_hw_uninit(hda_controller* controller);
status_t hda_send_verbs(hda_codec* codec, corb_t* verbs, uint32* responses, status_t hda_send_verbs(hda_codec* codec, corb_t* verbs, uint32* responses,
int count); uint32 count);
/* hda_controller.c: Stream support */ /* hda_controller.c: Stream support */
hda_stream* hda_stream_new(hda_controller* controller, int type); hda_stream* hda_stream_new(hda_controller* controller, int type);
@@ -174,7 +174,7 @@ hda_codec_parse_audio_group(hda_audio_group* audioGroup)
audioGroup->widget_start = resp[2] >> 16; audioGroup->widget_start = resp[2] >> 16;
audioGroup->widget_count = resp[2] & 0xFF; audioGroup->widget_count = resp[2] & 0xFF;
audioGroup->widgets = calloc(audioGroup->widget_count, audioGroup->widgets = (hda_widget*)calloc(audioGroup->widget_count,
sizeof(*audioGroup->widgets)); sizeof(*audioGroup->widgets));
if (audioGroup->widgets == NULL) { if (audioGroup->widgets == NULL) {
dprintf("ERROR: Not enough memory!\n"); dprintf("ERROR: Not enough memory!\n");
@@ -193,7 +193,7 @@ hda_codec_parse_audio_group(hda_audio_group* audioGroup)
PID_CONNLIST_LEN); PID_CONNLIST_LEN);
hda_send_verbs(audioGroup->codec, verbs, resp, 2); hda_send_verbs(audioGroup->codec, verbs, resp, 2);
audioGroup->widgets[widx].type = resp[0] >> 20; audioGroup->widgets[widx].type = (hda_widget_type)(resp[0] >> 20);
audioGroup->widgets[widx].num_inputs = resp[1] & 0x7F; audioGroup->widgets[widx].num_inputs = resp[1] & 0x7F;
off = 0; off = 0;
@@ -272,7 +272,8 @@ hda_codec_parse_audio_group(hda_audio_group* audioGroup)
verbs[0] = MAKE_VERB(audioGroup->codec->addr, wid, verbs[0] = MAKE_VERB(audioGroup->codec->addr, wid,
VID_GET_CFGDEFAULT, 0); VID_GET_CFGDEFAULT, 0);
if (hda_send_verbs(audioGroup->codec, verbs, resp, 1) == B_OK) { if (hda_send_verbs(audioGroup->codec, verbs, resp, 1) == B_OK) {
audioGroup->widgets[widx].d.pin.device = (resp[0] >> 20) & 0xF; audioGroup->widgets[widx].d.pin.device = (pin_dev_type)
((resp[0] >> 20) & 0xf);
dprintf("\t%s, %s, %s, %s\n", dprintf("\t%s, %s, %s, %s\n",
kPortConnector[resp[0] >> 30], kPortConnector[resp[0] >> 30],
kDefaultDevice[audioGroup->widgets[widx].d.pin.device], kDefaultDevice[audioGroup->widgets[widx].d.pin.device],
@@ -304,10 +305,6 @@ hda_codec_parse_audio_group(hda_audio_group* audioGroup)
&audioGroup->widgets[widx].pm); &audioGroup->widgets[widx].pm);
if (audioGroup->widgets[widx].num_inputs) { if (audioGroup->widgets[widx].num_inputs) {
int idx;
off = 0;
if (audioGroup->widgets[widx].num_inputs > 1) { if (audioGroup->widgets[widx].num_inputs > 1) {
verbs[0] = MAKE_VERB(audioGroup->codec->addr, wid, verbs[0] = MAKE_VERB(audioGroup->codec->addr, wid,
VID_GET_CONNSEL, 0); VID_GET_CONNSEL, 0);
@@ -318,10 +315,12 @@ hda_codec_parse_audio_group(hda_audio_group* audioGroup)
} else } else
audioGroup->widgets[widx].active_input = -1; audioGroup->widgets[widx].active_input = -1;
for (idx = 0; idx < audioGroup->widgets[widx].num_inputs; idx ++) { off = 0;
if (!(idx % 4)) {
for (uint32 i = 0; i < audioGroup->widgets[widx].num_inputs; i++) {
if (!(i % 4)) {
verbs[0] = MAKE_VERB(audioGroup->codec->addr, wid, verbs[0] = MAKE_VERB(audioGroup->codec->addr, wid,
VID_GET_CONNLENTRY, idx); VID_GET_CONNLENTRY, i);
if (hda_send_verbs(audioGroup->codec, verbs, resp, 1) != B_OK) { if (hda_send_verbs(audioGroup->codec, verbs, resp, 1) != B_OK) {
dprintf("%s: Error parsing inputs for widget %ld!\n", dprintf("%s: Error parsing inputs for widget %ld!\n",
__func__, wid); __func__, wid);
@@ -329,16 +328,16 @@ hda_codec_parse_audio_group(hda_audio_group* audioGroup)
} }
} }
if (idx != audioGroup->widgets[widx].active_input) { if ((int32)i != audioGroup->widgets[widx].active_input) {
off += sprintf(buf + off, "%ld ", off += sprintf(buf + off, "%ld ",
(resp[0] >> (8 * (idx % 4))) & 0xff); (resp[0] >> (8 * (i % 4))) & 0xff);
} else { } else {
off += sprintf(buf + off, "(%ld) ", off += sprintf(buf + off, "(%ld) ",
(resp[0] >> (8 * (idx % 4))) & 0xff); (resp[0] >> (8 * (i % 4))) & 0xff);
} }
audioGroup->widgets[widx].inputs[idx] audioGroup->widgets[widx].inputs[i]
= (resp[0] >> (8 * (idx % 4))) & 0xff; = (resp[0] >> (8 * (i % 4))) & 0xff;
} }
dprintf("\t[ %s]\n", buf); dprintf("\t[ %s]\n", buf);
@@ -349,35 +348,35 @@ hda_codec_parse_audio_group(hda_audio_group* audioGroup)
} }
/*! Find path from 'wid' to a widget of type 'wtype', returning its widget id. /*! Find path from 'wid' to a widget of type \a widgetType, returning its
* Returns 0 if not found. widget id.
*/ Returns 0 if not found.
*/
static uint32 static uint32
hda_codec_audio_group_find_path(hda_audio_group* audioGroup, uint32 widget, hda_codec_audio_group_find_path(hda_audio_group* audioGroup, uint32 widget,
uint32 widgetType, uint32 depth) hda_widget_type widgetType, uint32 depth)
{ {
int widx = widget - audioGroup->widget_start; int widx = widget - audioGroup->widget_start;
int idx;
switch (audioGroup->widgets[widx].type) { switch (audioGroup->widgets[widx].type) {
case WT_AUDIO_MIXER: case WT_AUDIO_MIXER:
for (idx = 0; idx < audioGroup->widgets[widx].num_inputs; idx++) { for (uint32 i = 0; i < audioGroup->widgets[widx].num_inputs; i++) {
if (hda_codec_audio_group_find_path(audioGroup, if (hda_codec_audio_group_find_path(audioGroup,
audioGroup->widgets[widx].inputs[idx], widgetType, audioGroup->widgets[widx].inputs[i], widgetType,
depth + 1)) { depth + 1)) {
if (audioGroup->widgets[widx].active_input == -1) if (audioGroup->widgets[widx].active_input == -1)
audioGroup->widgets[widx].active_input = idx; audioGroup->widgets[widx].active_input = i;
return audioGroup->widgets[widx].inputs[idx]; return audioGroup->widgets[widx].inputs[i];
} }
} }
break; break;
case WT_AUDIO_SELECTOR: case WT_AUDIO_SELECTOR:
{ {
int idx = audioGroup->widgets[widx].active_input; int32 i = audioGroup->widgets[widx].active_input;
if (idx != -1) { if (i != -1) {
widget = audioGroup->widgets[widx].inputs[idx]; widget = audioGroup->widgets[widx].inputs[i];
if (hda_codec_audio_group_find_path(audioGroup, widget, if (hda_codec_audio_group_find_path(audioGroup, widget,
widgetType, depth + 1)) { widgetType, depth + 1)) {
return widget; return widget;
@@ -417,49 +416,48 @@ hda_codec_delete_audio_group(hda_audio_group* audioGroup)
static status_t static status_t
hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID) hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID)
{ {
hda_audio_group* audioGroup; hda_audio_group* audioGroup = (hda_audio_group*)calloc(1,
status_t rc; sizeof(hda_audio_group));
uint32 idx; if (audioGroup == NULL)
return B_NO_MEMORY;
if ((audioGroup = calloc(1, sizeof(hda_audio_group))) == NULL) {
rc = B_NO_MEMORY;
goto done;
}
/* Setup minimal info needed by hda_codec_parse_afg */ /* Setup minimal info needed by hda_codec_parse_afg */
audioGroup->root_node_id = audioGroupNodeID; audioGroup->root_node_id = audioGroupNodeID;
audioGroup->codec = codec; audioGroup->codec = codec;
/* Parse all widgets in Audio Function Group */ /* Parse all widgets in Audio Function Group */
rc = hda_codec_parse_audio_group(audioGroup); status_t status = hda_codec_parse_audio_group(audioGroup);
if (rc != B_OK) if (status != B_OK)
goto free_audio_group; goto err;
/* Setup for worst-case scenario; we cannot find any output Pin Widgets */ /* Setup for worst-case scenario; we cannot find any output Pin Widgets */
rc = ENODEV; status = ENODEV;
/* Try to locate all input/output channels */ /* Try to locate all input/output channels */
for (idx = 0; idx < audioGroup->widget_count; idx++) { for (uint32 i = 0; i < audioGroup->widget_count; i++) {
uint32 outputWidget = 0, inputWidget = 0; uint32 outputWidget = 0, inputWidget = 0;
int32 iidx;
if (audioGroup->playback_stream == NULL if (audioGroup->playback_stream == NULL
&& audioGroup->widgets[idx].type == WT_PIN_COMPLEX && audioGroup->widgets[i].type == WT_PIN_COMPLEX
&& audioGroup->widgets[idx].d.pin.output) { && audioGroup->widgets[i].d.pin.output) {
if (audioGroup->widgets[idx].d.pin.device == PIN_DEV_HP_OUT if (audioGroup->widgets[i].d.pin.device == PIN_DEV_HP_OUT
|| audioGroup->widgets[idx].d.pin.device == PIN_DEV_SPEAKER || audioGroup->widgets[i].d.pin.device == PIN_DEV_SPEAKER
|| audioGroup->widgets[idx].d.pin.device == PIN_DEV_LINE_OUT) { || audioGroup->widgets[i].d.pin.device == PIN_DEV_LINE_OUT) {
iidx = audioGroup->widgets[idx].active_input; int32 inputIndex = audioGroup->widgets[i].active_input;
if (iidx != -1) { if (inputIndex != -1) {
outputWidget = hda_codec_audio_group_find_path(audioGroup, outputWidget = hda_codec_audio_group_find_path(audioGroup,
audioGroup->widgets[idx].inputs[iidx], WT_AUDIO_OUTPUT, 0); audioGroup->widgets[i].inputs[inputIndex],
WT_AUDIO_OUTPUT, 0);
} else { } else {
for (iidx = 0; iidx < audioGroup->widgets[idx].num_inputs; iidx++) { for (inputIndex = 0; (uint32)inputIndex
< audioGroup->widgets[i].num_inputs; inputIndex++) {
outputWidget = hda_codec_audio_group_find_path(audioGroup, outputWidget = hda_codec_audio_group_find_path(audioGroup,
audioGroup->widgets[idx].inputs[iidx], WT_AUDIO_OUTPUT, 0); audioGroup->widgets[i].inputs[inputIndex],
WT_AUDIO_OUTPUT, 0);
if (outputWidget) { if (outputWidget) {
corb_t verb = MAKE_VERB(codec->addr, corb_t verb = MAKE_VERB(codec->addr,
idx + audioGroup->widget_start, VID_SET_CONNSEL, iidx); i + audioGroup->widget_start, VID_SET_CONNSEL,
inputIndex);
if (hda_send_verbs(codec, &verb, NULL, 1) != B_OK) if (hda_send_verbs(codec, &verb, NULL, 1) != B_OK)
dprintf("%s: Setting output selector failed!\n", __func__); dprintf("%s: Setting output selector failed!\n", __func__);
break; break;
@@ -477,40 +475,45 @@ hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID)
audioGroup->record_stream = hda_stream_new( audioGroup->record_stream = hda_stream_new(
audioGroup->codec->controller, STREAM_RECORD); audioGroup->codec->controller, STREAM_RECORD);
audioGroup->playback_stream->pin_widget = idx audioGroup->playback_stream->pin_widget = i
+ audioGroup->widget_start; + audioGroup->widget_start;
audioGroup->playback_stream->io_widget = outputWidget; audioGroup->playback_stream->io_widget = outputWidget;
/* FIXME: Force Pin Widget to unmute; enable hp/output */ /* FIXME: Force Pin Widget to unmute; enable hp/output */
verb[0] = MAKE_VERB(codec->addr, verb[0] = MAKE_VERB(codec->addr,
audioGroup->playback_stream->pin_widget, VID_SET_AMPGAINMUTE, audioGroup->playback_stream->pin_widget,
VID_SET_AMPGAINMUTE,
(1 << 15) | (1 << 13) | (1 << 12)); (1 << 15) | (1 << 13) | (1 << 12));
verb[1] = MAKE_VERB(codec->addr, verb[1] = MAKE_VERB(codec->addr,
audioGroup->playback_stream->pin_widget, VID_SET_PINWCTRL, audioGroup->playback_stream->pin_widget,
VID_SET_PINWCTRL,
(1 << 7) | (1 << 6)); (1 << 7) | (1 << 6));
hda_send_verbs(codec, verb, NULL, 2); hda_send_verbs(codec, verb, NULL, 2);
dprintf("%s: Found output PIN (%s) connected to output " dprintf("%s: Found output PIN (%s) connected to output "
"CONV wid:%ld\n", __func__, "CONV wid:%ld\n", __func__,
kDefaultDevice[audioGroup->widgets[idx].d.pin.device], outputWidget); kDefaultDevice[audioGroup->widgets[i].d.pin.device], outputWidget);
} }
} }
} }
} }
if (audioGroup->widgets[idx].type == WT_AUDIO_INPUT) { if (audioGroup->widgets[i].type == WT_AUDIO_INPUT) {
iidx = audioGroup->widgets[idx].active_input; int32 inputIndex = audioGroup->widgets[i].active_input;
if (iidx != -1) { if (inputIndex != -1) {
inputWidget = hda_codec_audio_group_find_path(audioGroup, inputWidget = hda_codec_audio_group_find_path(audioGroup,
audioGroup->widgets[idx].inputs[iidx], WT_PIN_COMPLEX, 0); audioGroup->widgets[i].inputs[inputIndex], WT_PIN_COMPLEX,
0);
} else { } else {
for (iidx = 0; iidx < audioGroup->widgets[idx].num_inputs; iidx++) { for (inputIndex = 0; (uint32)inputIndex
< audioGroup->widgets[i].num_inputs; inputIndex++) {
inputWidget = hda_codec_audio_group_find_path(audioGroup, inputWidget = hda_codec_audio_group_find_path(audioGroup,
audioGroup->widgets[idx].inputs[iidx], WT_PIN_COMPLEX, 0); audioGroup->widgets[i].inputs[inputIndex],
WT_PIN_COMPLEX, 0);
if (inputWidget) { if (inputWidget) {
corb_t verb = MAKE_VERB(codec->addr, corb_t verb = MAKE_VERB(codec->addr,
idx + audioGroup->widget_start, VID_SET_CONNSEL, i + audioGroup->widget_start, VID_SET_CONNSEL,
iidx); inputIndex);
if (hda_send_verbs(codec, &verb, NULL, 1) != B_OK) { if (hda_send_verbs(codec, &verb, NULL, 1) != B_OK) {
dprintf("%s: Setting input selector failed!\n", dprintf("%s: Setting input selector failed!\n",
__func__); __func__);
@@ -529,7 +532,7 @@ hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID)
audioGroup->codec->controller, STREAM_RECORD); audioGroup->codec->controller, STREAM_RECORD);
audioGroup->record_stream->pin_widget = inputWidget; audioGroup->record_stream->pin_widget = inputWidget;
audioGroup->record_stream->io_widget = idx audioGroup->record_stream->io_widget = i
+ audioGroup->widget_start; + audioGroup->widget_start;
/* FIXME: Force Pin Widget to unmute */ /* FIXME: Force Pin Widget to unmute */
@@ -542,7 +545,7 @@ hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID)
dprintf("%s: Found input PIN (%s) connected to input CONV " dprintf("%s: Found input PIN (%s) connected to input CONV "
"wid:%ld\n", __func__, kDefaultDevice[audioGroup->widgets[ "wid:%ld\n", __func__, kDefaultDevice[audioGroup->widgets[
inputWidget - audioGroup->widget_start].d.pin.device], inputWidget - audioGroup->widget_start].d.pin.device],
idx + audioGroup->widget_start); i + audioGroup->widget_start);
} }
} }
} }
@@ -550,15 +553,12 @@ hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID)
/* If we found any valid output channels, we're in the clear */ /* If we found any valid output channels, we're in the clear */
if (audioGroup && audioGroup->playback_stream) { if (audioGroup && audioGroup->playback_stream) {
codec->audio_groups[codec->num_audio_groups++] = audioGroup; codec->audio_groups[codec->num_audio_groups++] = audioGroup;
rc = B_OK; return B_OK;
goto done;
} }
free_audio_group: err:
free(audioGroup); free(audioGroup);
return status;
done:
return rc;
} }
@@ -586,7 +586,7 @@ hda_codec_delete(hda_codec* codec)
hda_codec* hda_codec*
hda_codec_new(hda_controller* controller, uint32 cad) hda_codec_new(hda_controller* controller, uint32 cad)
{ {
hda_codec* codec = calloc(1, sizeof(hda_codec)); hda_codec* codec = (hda_codec*)calloc(1, sizeof(hda_codec));
uint32 responses[3]; uint32 responses[3];
corb_t verbs[3]; corb_t verbs[3];
uint32 nodeID; uint32 nodeID;
@@ -8,7 +8,7 @@
#ifndef HDA_CODEC_H #ifndef HDA_CODEC_H
#define HDA_CODEC_H #define HDA_CODEC_H
typedef enum { enum hda_widget_type {
WT_AUDIO_OUTPUT = 0, WT_AUDIO_OUTPUT = 0,
WT_AUDIO_INPUT = 1, WT_AUDIO_INPUT = 1,
WT_AUDIO_MIXER = 2, WT_AUDIO_MIXER = 2,
@@ -18,10 +18,10 @@ typedef enum {
WT_VOLUME_KNOB = 6, WT_VOLUME_KNOB = 6,
WT_BEEP_GENERATOR = 7, WT_BEEP_GENERATOR = 7,
WT_VENDOR_DEFINED = 15 WT_VENDOR_DEFINED = 15
} hda_widget_type; };
typedef enum { enum pin_dev_type {
PIN_DEV_LINE_OUT = 0, PIN_DEV_LINE_OUT = 0,
PIN_DEV_SPEAKER, PIN_DEV_SPEAKER,
PIN_DEV_HP_OUT, PIN_DEV_HP_OUT,
@@ -38,7 +38,7 @@ typedef enum {
PIN_DEV_DIGITAL_OTHER_IN, PIN_DEV_DIGITAL_OTHER_IN,
PIN_DEV_RESERVED, PIN_DEV_RESERVED,
PIN_DEV_OTHER PIN_DEV_OTHER
} pin_dev_type; };
/* Verb Helper Macro */ /* Verb Helper Macro */
@@ -4,6 +4,7 @@
* *
* Authors: * Authors:
* Ithamar Adema, ithamar AT unet DOT nl * Ithamar Adema, ithamar AT unet DOT nl
* Axel Dörfler, axeld@pinc-software.de
*/ */
@@ -79,7 +80,7 @@ hda_stream_delete(hda_stream* stream)
hda_stream* hda_stream*
hda_stream_new(hda_controller* controller, int type) hda_stream_new(hda_controller* controller, int type)
{ {
hda_stream* stream = calloc(1, sizeof(hda_stream)); hda_stream* stream = (hda_stream*)calloc(1, sizeof(hda_stream));
if (stream == NULL) if (stream == NULL)
return NULL; return NULL;
@@ -333,7 +334,7 @@ dprintf("HDA: sample size %ld, num channels %ld, buffer length %ld *************
status_t status_t
hda_send_verbs(hda_codec* codec, corb_t* verbs, uint32* responses, int count) hda_send_verbs(hda_codec* codec, corb_t* verbs, uint32* responses, uint32 count)
{ {
hda_controller *controller = codec->controller; hda_controller *controller = codec->controller;
uint32 sent = 0; uint32 sent = 0;
@@ -410,7 +411,7 @@ hda_interrupt_handler(hda_controller* controller)
if ((responseFlags & RESPONSE_FLAGS_UNSOLICITED) != 0) { if ((responseFlags & RESPONSE_FLAGS_UNSOLICITED) != 0) {
dprintf("hda: Unsolicited response: %08lx/%08lx\n", dprintf("hda: Unsolicited response: %08lx/%08lx\n",
response, extendedResponse); response, responseFlags);
continue; continue;
} }
if (codec == NULL) { if (codec == NULL) {
@@ -188,11 +188,6 @@ 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 playbackSampleSize = audioGroup->playback_stream->sample_size;
uint32 recordSampleSize = audioGroup->record_stream->sample_size;
uint32 cidx, bidx;
status_t status;
TRACE("playback: %ld buffers, %ld channels, %ld samples\n", TRACE("playback: %ld buffers, %ld channels, %ld samples\n",
data->request_playback_buffers, data->request_playback_channels, data->request_playback_buffers, data->request_playback_channels,
data->request_playback_buffer_size); data->request_playback_buffer_size);
@@ -237,8 +232,8 @@ get_buffers(hda_audio_group* audioGroup, multi_buffer_list* data)
audioGroup->playback_stream->buffer_length audioGroup->playback_stream->buffer_length
= data->return_playback_buffer_size; = data->return_playback_buffer_size;
status = hda_stream_setup_buffers(audioGroup, audioGroup->playback_stream, status_t status = hda_stream_setup_buffers(audioGroup,
"Playback"); audioGroup->playback_stream, "Playback");
if (status != B_OK) { if (status != B_OK) {
dprintf("hda: Error setting up playback buffers: %s\n", dprintf("hda: Error setting up playback buffers: %s\n",
strerror(status)); strerror(status));
@@ -260,22 +255,27 @@ get_buffers(hda_audio_group* audioGroup, multi_buffer_list* data)
/* Setup data structure for multi_audio API... */ /* Setup data structure for multi_audio API... */
for (bidx = 0; bidx < data->return_playback_buffers; bidx++) { uint32 playbackSampleSize = audioGroup->playback_stream->sample_size;
for (cidx = 0; cidx < data->return_playback_channels; cidx++) { uint32 recordSampleSize = audioGroup->record_stream->sample_size;
data->playback_buffers[bidx][cidx].base
= audioGroup->playback_stream->buffers[bidx] for (int32 i = 0; i < data->return_playback_buffers; i++) {
+ playbackSampleSize * cidx; for (int32 channelIndex = 0;
data->playback_buffers[bidx][cidx].stride channelIndex < data->return_playback_channels; channelIndex++) {
data->playback_buffers[i][channelIndex].base
= (char*)audioGroup->playback_stream->buffers[i]
+ playbackSampleSize * channelIndex;
data->playback_buffers[i][channelIndex].stride
= playbackSampleSize * data->return_playback_channels; = playbackSampleSize * data->return_playback_channels;
} }
} }
for (bidx = 0; bidx < data->return_record_buffers; bidx++) { for (int32 i = 0; i < data->return_record_buffers; i++) {
for (cidx = 0; cidx < data->return_record_channels; cidx++) { for (int32 channelIndex = 0;
data->record_buffers[bidx][cidx].base channelIndex < data->return_record_channels; channelIndex++) {
= audioGroup->record_stream->buffers[bidx] data->record_buffers[i][channelIndex].base
+ recordSampleSize * cidx; = (char*)audioGroup->record_stream->buffers[i]
data->record_buffers[bidx][cidx].stride + recordSampleSize * channelIndex;
data->record_buffers[i][channelIndex].stride
= recordSampleSize * data->return_record_channels; = recordSampleSize * data->return_record_channels;
} }
} }
@@ -347,31 +347,34 @@ multi_audio_control(void* cookie, uint32 op, void* arg, size_t len)
audioGroup = codec->audio_groups[0]; audioGroup = codec->audio_groups[0];
// TODO: make userland-safe when built for Haiku!
switch (op) { switch (op) {
case B_MULTI_GET_DESCRIPTION: case B_MULTI_GET_DESCRIPTION:
return get_description(audioGroup, arg); return get_description(audioGroup, (multi_description*)arg);
case B_MULTI_GET_ENABLED_CHANNELS: case B_MULTI_GET_ENABLED_CHANNELS:
return get_enabled_channels(audioGroup, arg); return get_enabled_channels(audioGroup, (multi_channel_enable*)arg);
case B_MULTI_SET_ENABLED_CHANNELS: case B_MULTI_SET_ENABLED_CHANNELS:
return B_OK; return B_OK;
case B_MULTI_GET_GLOBAL_FORMAT: case B_MULTI_GET_GLOBAL_FORMAT:
return get_global_format(audioGroup, arg); return get_global_format(audioGroup, (multi_format_info*)arg);
case B_MULTI_SET_GLOBAL_FORMAT: case B_MULTI_SET_GLOBAL_FORMAT:
return set_global_format(audioGroup, arg); return set_global_format(audioGroup, (multi_format_info*)arg);
case B_MULTI_LIST_MIX_CHANNELS: case B_MULTI_LIST_MIX_CHANNELS:
return list_mix_channels(audioGroup, arg); return list_mix_channels(audioGroup, (multi_mix_channel_info*)arg);
case B_MULTI_LIST_MIX_CONTROLS: case B_MULTI_LIST_MIX_CONTROLS:
return list_mix_controls(audioGroup, arg); return list_mix_controls(audioGroup, (multi_mix_control_info*)arg);
case B_MULTI_LIST_MIX_CONNECTIONS: case B_MULTI_LIST_MIX_CONNECTIONS:
return list_mix_connections(audioGroup, arg); return list_mix_connections(audioGroup,
(multi_mix_connection_info*)arg);
case B_MULTI_GET_BUFFERS: case B_MULTI_GET_BUFFERS:
return get_buffers(audioGroup, arg); return get_buffers(audioGroup, (multi_buffer_list*)arg);
case B_MULTI_BUFFER_EXCHANGE: case B_MULTI_BUFFER_EXCHANGE:
return buffer_exchange(audioGroup, arg); return buffer_exchange(audioGroup, (multi_buffer_info*)arg);
case B_MULTI_BUFFER_FORCE_STOP: case B_MULTI_BUFFER_FORCE_STOP:
return buffer_force_stop(audioGroup); return buffer_force_stop(audioGroup);