[haiku-commits] r35088 - haiku/trunk/src/add-ons/kernel/drivers/audio/hda

  • From: korli@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 15 Jan 2010 23:07:42 +0100 (CET)

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) {


Other related posts: