* 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:
@@ -286,8 +286,10 @@ struct hda_codec {
|
|||||||
uint32 responses[MAX_CODEC_RESPONSES];
|
uint32 responses[MAX_CODEC_RESPONSES];
|
||||||
uint32 response_count;
|
uint32 response_count;
|
||||||
|
|
||||||
|
sem_id unsol_response_sem;
|
||||||
|
thread_id unsol_response_thread;
|
||||||
uint32 unsol_responses[MAX_CODEC_UNSOL_RESPONSES];
|
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];
|
hda_audio_group* audio_groups[HDA_MAX_AUDIO_GROUPS];
|
||||||
uint32 num_audio_groups;
|
uint32 num_audio_groups;
|
||||||
|
|||||||
@@ -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
|
static void
|
||||||
hda_codec_delete_audio_group(hda_audio_group* audioGroup)
|
hda_codec_delete_audio_group(hda_audio_group* audioGroup)
|
||||||
{
|
{
|
||||||
@@ -1313,6 +1346,10 @@ hda_codec_delete(hda_codec* codec)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
delete_sem(codec->response_sem);
|
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++) {
|
for (uint32 i = 0; i < codec->num_audio_groups; i++) {
|
||||||
hda_codec_delete_audio_group(codec->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->controller = controller;
|
||||||
codec->addr = codecAddress;
|
codec->addr = codecAddress;
|
||||||
codec->response_sem = create_sem(0, "hda_codec_response_sem");
|
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;
|
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 {
|
struct {
|
||||||
uint32 device : 16;
|
uint32 device : 16;
|
||||||
uint32 vendor : 16;
|
uint32 vendor : 16;
|
||||||
@@ -1401,7 +1457,6 @@ hda_codec_new(hda_controller* controller, uint32 codecAddress)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return codec;
|
return codec;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
controller->codecs[codecAddress] = NULL;
|
controller->codecs[codecAddress] = NULL;
|
||||||
hda_codec_delete(codec);
|
hda_codec_delete(codec);
|
||||||
|
|||||||
@@ -211,14 +211,12 @@ 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, responseFlags);
|
response, responseFlags);
|
||||||
if (codec->unsol_response_count >= MAX_CODEC_UNSOL_RESPONSES) {
|
codec->unsol_responses[codec->unsol_response_write++] =
|
||||||
dprintf("hda: too many unsol responses received"
|
|
||||||
" for codec %ld: %08lx/%08lx!\n",
|
|
||||||
cad, response, responseFlags);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
codec->unsol_responses[codec->unsol_response_count++] =
|
|
||||||
response;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
if (codec->response_count >= MAX_CODEC_RESPONSES) {
|
if (codec->response_count >= MAX_CODEC_RESPONSES) {
|
||||||
|
|||||||
Reference in New Issue
Block a user