* We now mute internal speakers when using headphones. We don't distinguish between headphones and mic jacks though.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35088 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval 2010-01-15 22:07:42 +00:00
parent fc844f7bfb
commit e25dcf1a96
3 changed files with 65 additions and 10 deletions

View File

@ -286,8 +286,10 @@ struct hda_codec {
uint32 responses[MAX_CODEC_RESPONSES];
uint32 response_count;
sem_id unsol_response_sem;
thread_id unsol_response_thread;
uint32 unsol_responses[MAX_CODEC_UNSOL_RESPONSES];
uint32 unsol_response_count;
uint32 unsol_response_read, unsol_response_write;
hda_audio_group* audio_groups[HDA_MAX_AUDIO_GROUPS];
uint32 num_audio_groups;

View File

@ -1092,6 +1092,39 @@ hda_codec_switch_init(hda_audio_group* audioGroup)
}
static status_t
hda_codec_switch_handler(hda_codec* codec)
{
while (acquire_sem(codec->unsol_response_sem) == B_OK) {
uint32 response = codec->unsol_responses[codec->unsol_response_read++];
codec->unsol_response_read %= MAX_CODEC_UNSOL_RESPONSES;
bool disable = response & 1;
hda_audio_group* audioGroup = codec->audio_groups[0];
for (uint32 i = 0; i < audioGroup->widget_count; i++) {
hda_widget& widget = audioGroup->widgets[i];
if (widget.type != WT_PIN_COMPLEX || !PIN_CAP_IS_OUTPUT(widget.d.pin.capabilities))
continue;
int device = CONF_DEFAULT_DEVICE(widget.d.pin.config);
if (device != PIN_DEV_SPEAKER
&& device != PIN_DEV_LINE_OUT)
continue;
uint32 ctrl = hda_widget_prepare_pin_ctrl(audioGroup, &widget,
true);
corb_t verb = MAKE_VERB(audioGroup->codec->addr, widget.node_id,
VID_SET_PIN_WIDGET_CONTROL, disable ? 0 : ctrl);
hda_send_verbs(audioGroup->codec, &verb, NULL, 1);
}
}
return B_OK;
}
static void
hda_codec_delete_audio_group(hda_audio_group* audioGroup)
{
@ -1313,6 +1346,10 @@ hda_codec_delete(hda_codec* codec)
return;
delete_sem(codec->response_sem);
delete_sem(codec->unsol_response_sem);
int32 result;
wait_for_thread(codec->unsol_response_thread, &result);
for (uint32 i = 0; i < codec->num_audio_groups; i++) {
hda_codec_delete_audio_group(codec->audio_groups[i]);
@ -1338,9 +1375,28 @@ hda_codec_new(hda_controller* controller, uint32 codecAddress)
codec->controller = controller;
codec->addr = codecAddress;
codec->response_sem = create_sem(0, "hda_codec_response_sem");
codec->unsol_response_count = 0;
if (codec->response_sem < B_OK) {
ERROR("hda: Failed to create semaphore\n");
goto err;
}
controller->codecs[codecAddress] = codec;
codec->unsol_response_sem = create_sem(0, "hda_codec_unsol_response_sem");
if (codec->unsol_response_sem < B_OK) {
ERROR("hda: Failed to create semaphore\n");
goto err;
}
codec->unsol_response_read = 0;
codec->unsol_response_write = 0;
codec->unsol_response_thread = spawn_kernel_thread(
(status_t(*)(void*))hda_codec_switch_handler,
"hda_codec_unsol_thread", B_LOW_PRIORITY, codec);
if (codec->unsol_response_thread < B_OK) {
ERROR("hda: Failed to spawn thread\n");
goto err;
}
resume_thread(codec->unsol_response_thread);
struct {
uint32 device : 16;
uint32 vendor : 16;
@ -1401,7 +1457,6 @@ hda_codec_new(hda_controller* controller, uint32 codecAddress)
}
return codec;
err:
controller->codecs[codecAddress] = NULL;
hda_codec_delete(codec);

View File

@ -211,14 +211,12 @@ hda_interrupt_handler(hda_controller* controller)
if ((responseFlags & RESPONSE_FLAGS_UNSOLICITED) != 0) {
dprintf("hda: Unsolicited response: %08lx/%08lx\n",
response, responseFlags);
if (codec->unsol_response_count >= MAX_CODEC_UNSOL_RESPONSES) {
dprintf("hda: too many unsol responses received"
" for codec %ld: %08lx/%08lx!\n",
cad, response, responseFlags);
continue;
}
codec->unsol_responses[codec->unsol_response_count++] =
codec->unsol_responses[codec->unsol_response_write++] =
response;
codec->unsol_response_write %= MAX_CODEC_UNSOL_RESPONSES;
release_sem_etc(codec->unsol_response_sem, 1,
B_DO_NOT_RESCHEDULE);
handled = B_INVOKE_SCHEDULER;
continue;
}
if (codec->response_count >= MAX_CODEC_RESPONSES) {