Author: korli Date: 2010-01-15 23:07:42 +0100 (Fri, 15 Jan 2010) New Revision: 35088 Changeset: http://dev.haiku-os.org/changeset/35088/haiku Modified: haiku/trunk/src/add-ons/kernel/drivers/audio/hda/driver.h haiku/trunk/src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp haiku/trunk/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp Log: * We now mute internal speakers when using headphones. We don't distinguish between headphones and mic jacks though. Modified: haiku/trunk/src/add-ons/kernel/drivers/audio/hda/driver.h =================================================================== --- haiku/trunk/src/add-ons/kernel/drivers/audio/hda/driver.h 2010-01-15 19:21:52 UTC (rev 35087) +++ haiku/trunk/src/add-ons/kernel/drivers/audio/hda/driver.h 2010-01-15 22:07:42 UTC (rev 35088) @@ -286,8 +286,10 @@ 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; Modified: haiku/trunk/src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp 2010-01-15 19:21:52 UTC (rev 35087) +++ haiku/trunk/src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp 2010-01-15 22:07:42 UTC (rev 35088) @@ -1092,6 +1092,39 @@ } +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 @@ 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 @@ 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 @@ } return codec; - err: controller->codecs[codecAddress] = NULL; hda_codec_delete(codec); Modified: haiku/trunk/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp 2010-01-15 19:21:52 UTC (rev 35087) +++ haiku/trunk/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp 2010-01-15 22:07:42 UTC (rev 35088) @@ -211,14 +211,12 @@ 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) {