diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 353 |
1 files changed, 262 insertions, 91 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index f26e487eca1c..9c27a3a4c4d5 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -243,7 +243,8 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, | |||
243 | { | 243 | { |
244 | unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm); | 244 | unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm); |
245 | unsigned int res; | 245 | unsigned int res; |
246 | codec_exec_verb(codec, cmd, &res); | 246 | if (codec_exec_verb(codec, cmd, &res)) |
247 | return -1; | ||
247 | return res; | 248 | return res; |
248 | } | 249 | } |
249 | EXPORT_SYMBOL_HDA(snd_hda_codec_read); | 250 | EXPORT_SYMBOL_HDA(snd_hda_codec_read); |
@@ -307,63 +308,107 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, | |||
307 | } | 308 | } |
308 | EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes); | 309 | EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes); |
309 | 310 | ||
310 | static int _hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | 311 | /* look up the cached results */ |
311 | hda_nid_t *conn_list, int max_conns); | 312 | static hda_nid_t *lookup_conn_list(struct snd_array *array, hda_nid_t nid) |
312 | static bool add_conn_list(struct snd_array *array, hda_nid_t nid); | 313 | { |
313 | static int copy_conn_list(hda_nid_t nid, hda_nid_t *dst, int max_dst, | 314 | int i, len; |
314 | hda_nid_t *src, int len); | 315 | for (i = 0; i < array->used; ) { |
316 | hda_nid_t *p = snd_array_elem(array, i); | ||
317 | if (nid == *p) | ||
318 | return p; | ||
319 | len = p[1]; | ||
320 | i += len + 2; | ||
321 | } | ||
322 | return NULL; | ||
323 | } | ||
315 | 324 | ||
316 | /** | 325 | /** |
317 | * snd_hda_get_connections - get connection list | 326 | * snd_hda_get_conn_list - get connection list |
318 | * @codec: the HDA codec | 327 | * @codec: the HDA codec |
319 | * @nid: NID to parse | 328 | * @nid: NID to parse |
320 | * @conn_list: connection list array | 329 | * @listp: the pointer to store NID list |
321 | * @max_conns: max. number of connections to store | ||
322 | * | 330 | * |
323 | * Parses the connection list of the given widget and stores the list | 331 | * Parses the connection list of the given widget and stores the list |
324 | * of NIDs. | 332 | * of NIDs. |
325 | * | 333 | * |
326 | * Returns the number of connections, or a negative error code. | 334 | * Returns the number of connections, or a negative error code. |
327 | */ | 335 | */ |
328 | int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | 336 | int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid, |
329 | hda_nid_t *conn_list, int max_conns) | 337 | const hda_nid_t **listp) |
330 | { | 338 | { |
331 | struct snd_array *array = &codec->conn_lists; | 339 | struct snd_array *array = &codec->conn_lists; |
332 | int i, len, old_used; | 340 | int len, err; |
333 | hda_nid_t list[HDA_MAX_CONNECTIONS]; | 341 | hda_nid_t list[HDA_MAX_CONNECTIONS]; |
342 | hda_nid_t *p; | ||
343 | bool added = false; | ||
334 | 344 | ||
335 | /* look up the cached results */ | 345 | again: |
336 | for (i = 0; i < array->used; ) { | 346 | /* if the connection-list is already cached, read it */ |
337 | hda_nid_t *p = snd_array_elem(array, i); | 347 | p = lookup_conn_list(array, nid); |
338 | len = p[1]; | 348 | if (p) { |
339 | if (nid == *p) | 349 | if (listp) |
340 | return copy_conn_list(nid, conn_list, max_conns, | 350 | *listp = p + 2; |
341 | p + 2, len); | 351 | return p[1]; |
342 | i += len + 2; | ||
343 | } | 352 | } |
353 | if (snd_BUG_ON(added)) | ||
354 | return -EINVAL; | ||
344 | 355 | ||
345 | len = _hda_get_connections(codec, nid, list, HDA_MAX_CONNECTIONS); | 356 | /* read the connection and add to the cache */ |
357 | len = snd_hda_get_raw_connections(codec, nid, list, HDA_MAX_CONNECTIONS); | ||
346 | if (len < 0) | 358 | if (len < 0) |
347 | return len; | 359 | return len; |
360 | err = snd_hda_override_conn_list(codec, nid, len, list); | ||
361 | if (err < 0) | ||
362 | return err; | ||
363 | added = true; | ||
364 | goto again; | ||
365 | } | ||
366 | EXPORT_SYMBOL_HDA(snd_hda_get_conn_list); | ||
348 | 367 | ||
349 | /* add to the cache */ | 368 | /** |
350 | old_used = array->used; | 369 | * snd_hda_get_connections - copy connection list |
351 | if (!add_conn_list(array, nid) || !add_conn_list(array, len)) | 370 | * @codec: the HDA codec |
352 | goto error_add; | 371 | * @nid: NID to parse |
353 | for (i = 0; i < len; i++) | 372 | * @conn_list: connection list array |
354 | if (!add_conn_list(array, list[i])) | 373 | * @max_conns: max. number of connections to store |
355 | goto error_add; | 374 | * |
375 | * Parses the connection list of the given widget and stores the list | ||
376 | * of NIDs. | ||
377 | * | ||
378 | * Returns the number of connections, or a negative error code. | ||
379 | */ | ||
380 | int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | ||
381 | hda_nid_t *conn_list, int max_conns) | ||
382 | { | ||
383 | const hda_nid_t *list; | ||
384 | int len = snd_hda_get_conn_list(codec, nid, &list); | ||
356 | 385 | ||
357 | return copy_conn_list(nid, conn_list, max_conns, list, len); | 386 | if (len <= 0) |
358 | 387 | return len; | |
359 | error_add: | 388 | if (len > max_conns) { |
360 | array->used = old_used; | 389 | snd_printk(KERN_ERR "hda_codec: " |
361 | return -ENOMEM; | 390 | "Too many connections %d for NID 0x%x\n", |
391 | len, nid); | ||
392 | return -EINVAL; | ||
393 | } | ||
394 | memcpy(conn_list, list, len * sizeof(hda_nid_t)); | ||
395 | return len; | ||
362 | } | 396 | } |
363 | EXPORT_SYMBOL_HDA(snd_hda_get_connections); | 397 | EXPORT_SYMBOL_HDA(snd_hda_get_connections); |
364 | 398 | ||
365 | static int _hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | 399 | /** |
366 | hda_nid_t *conn_list, int max_conns) | 400 | * snd_hda_get_raw_connections - copy connection list without cache |
401 | * @codec: the HDA codec | ||
402 | * @nid: NID to parse | ||
403 | * @conn_list: connection list array | ||
404 | * @max_conns: max. number of connections to store | ||
405 | * | ||
406 | * Like snd_hda_get_connections(), copy the connection list but without | ||
407 | * checking through the connection-list cache. | ||
408 | * Currently called only from hda_proc.c, so not exported. | ||
409 | */ | ||
410 | int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid, | ||
411 | hda_nid_t *conn_list, int max_conns) | ||
367 | { | 412 | { |
368 | unsigned int parm; | 413 | unsigned int parm; |
369 | int i, conn_len, conns; | 414 | int i, conn_len, conns; |
@@ -376,11 +421,8 @@ static int _hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | |||
376 | 421 | ||
377 | wcaps = get_wcaps(codec, nid); | 422 | wcaps = get_wcaps(codec, nid); |
378 | if (!(wcaps & AC_WCAP_CONN_LIST) && | 423 | if (!(wcaps & AC_WCAP_CONN_LIST) && |
379 | get_wcaps_type(wcaps) != AC_WID_VOL_KNB) { | 424 | get_wcaps_type(wcaps) != AC_WID_VOL_KNB) |
380 | snd_printk(KERN_WARNING "hda_codec: " | 425 | return 0; |
381 | "connection list not available for 0x%x\n", nid); | ||
382 | return -EINVAL; | ||
383 | } | ||
384 | 426 | ||
385 | parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN); | 427 | parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN); |
386 | if (parm & AC_CLIST_LONG) { | 428 | if (parm & AC_CLIST_LONG) { |
@@ -470,18 +512,77 @@ static bool add_conn_list(struct snd_array *array, hda_nid_t nid) | |||
470 | return true; | 512 | return true; |
471 | } | 513 | } |
472 | 514 | ||
473 | static int copy_conn_list(hda_nid_t nid, hda_nid_t *dst, int max_dst, | 515 | /** |
474 | hda_nid_t *src, int len) | 516 | * snd_hda_override_conn_list - add/modify the connection-list to cache |
517 | * @codec: the HDA codec | ||
518 | * @nid: NID to parse | ||
519 | * @len: number of connection list entries | ||
520 | * @list: the list of connection entries | ||
521 | * | ||
522 | * Add or modify the given connection-list to the cache. If the corresponding | ||
523 | * cache already exists, invalidate it and append a new one. | ||
524 | * | ||
525 | * Returns zero or a negative error code. | ||
526 | */ | ||
527 | int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int len, | ||
528 | const hda_nid_t *list) | ||
529 | { | ||
530 | struct snd_array *array = &codec->conn_lists; | ||
531 | hda_nid_t *p; | ||
532 | int i, old_used; | ||
533 | |||
534 | p = lookup_conn_list(array, nid); | ||
535 | if (p) | ||
536 | *p = -1; /* invalidate the old entry */ | ||
537 | |||
538 | old_used = array->used; | ||
539 | if (!add_conn_list(array, nid) || !add_conn_list(array, len)) | ||
540 | goto error_add; | ||
541 | for (i = 0; i < len; i++) | ||
542 | if (!add_conn_list(array, list[i])) | ||
543 | goto error_add; | ||
544 | return 0; | ||
545 | |||
546 | error_add: | ||
547 | array->used = old_used; | ||
548 | return -ENOMEM; | ||
549 | } | ||
550 | EXPORT_SYMBOL_HDA(snd_hda_override_conn_list); | ||
551 | |||
552 | /** | ||
553 | * snd_hda_get_conn_index - get the connection index of the given NID | ||
554 | * @codec: the HDA codec | ||
555 | * @mux: NID containing the list | ||
556 | * @nid: NID to select | ||
557 | * @recursive: 1 when searching NID recursively, otherwise 0 | ||
558 | * | ||
559 | * Parses the connection list of the widget @mux and checks whether the | ||
560 | * widget @nid is present. If it is, return the connection index. | ||
561 | * Otherwise it returns -1. | ||
562 | */ | ||
563 | int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, | ||
564 | hda_nid_t nid, int recursive) | ||
475 | { | 565 | { |
476 | if (len > max_dst) { | 566 | hda_nid_t conn[HDA_MAX_NUM_INPUTS]; |
477 | snd_printk(KERN_ERR "hda_codec: " | 567 | int i, nums; |
478 | "Too many connections %d for NID 0x%x\n", | 568 | |
479 | len, nid); | 569 | nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn)); |
480 | return -EINVAL; | 570 | for (i = 0; i < nums; i++) |
571 | if (conn[i] == nid) | ||
572 | return i; | ||
573 | if (!recursive) | ||
574 | return -1; | ||
575 | if (recursive > 5) { | ||
576 | snd_printd("hda_codec: too deep connection for 0x%x\n", nid); | ||
577 | return -1; | ||
481 | } | 578 | } |
482 | memcpy(dst, src, len * sizeof(hda_nid_t)); | 579 | recursive++; |
483 | return len; | 580 | for (i = 0; i < nums; i++) |
581 | if (snd_hda_get_conn_index(codec, conn[i], nid, recursive) >= 0) | ||
582 | return i; | ||
583 | return -1; | ||
484 | } | 584 | } |
585 | EXPORT_SYMBOL_HDA(snd_hda_get_conn_index); | ||
485 | 586 | ||
486 | /** | 587 | /** |
487 | * snd_hda_queue_unsol_event - add an unsolicited event to queue | 588 | * snd_hda_queue_unsol_event - add an unsolicited event to queue |
@@ -1083,6 +1184,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
1083 | snd_array_free(&codec->mixers); | 1184 | snd_array_free(&codec->mixers); |
1084 | snd_array_free(&codec->nids); | 1185 | snd_array_free(&codec->nids); |
1085 | snd_array_free(&codec->conn_lists); | 1186 | snd_array_free(&codec->conn_lists); |
1187 | snd_array_free(&codec->spdif_out); | ||
1086 | codec->bus->caddr_tbl[codec->addr] = NULL; | 1188 | codec->bus->caddr_tbl[codec->addr] = NULL; |
1087 | if (codec->patch_ops.free) | 1189 | if (codec->patch_ops.free) |
1088 | codec->patch_ops.free(codec); | 1190 | codec->patch_ops.free(codec); |
@@ -1144,6 +1246,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, | |||
1144 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); | 1246 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); |
1145 | snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8); | 1247 | snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8); |
1146 | snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64); | 1248 | snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64); |
1249 | snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16); | ||
1147 | if (codec->bus->modelname) { | 1250 | if (codec->bus->modelname) { |
1148 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); | 1251 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); |
1149 | if (!codec->modelname) { | 1252 | if (!codec->modelname) { |
@@ -2555,11 +2658,13 @@ static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol, | |||
2555 | struct snd_ctl_elem_value *ucontrol) | 2658 | struct snd_ctl_elem_value *ucontrol) |
2556 | { | 2659 | { |
2557 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2660 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
2661 | int idx = kcontrol->private_value; | ||
2662 | struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); | ||
2558 | 2663 | ||
2559 | ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff; | 2664 | ucontrol->value.iec958.status[0] = spdif->status & 0xff; |
2560 | ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff; | 2665 | ucontrol->value.iec958.status[1] = (spdif->status >> 8) & 0xff; |
2561 | ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff; | 2666 | ucontrol->value.iec958.status[2] = (spdif->status >> 16) & 0xff; |
2562 | ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff; | 2667 | ucontrol->value.iec958.status[3] = (spdif->status >> 24) & 0xff; |
2563 | 2668 | ||
2564 | return 0; | 2669 | return 0; |
2565 | } | 2670 | } |
@@ -2644,23 +2749,23 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, | |||
2644 | struct snd_ctl_elem_value *ucontrol) | 2749 | struct snd_ctl_elem_value *ucontrol) |
2645 | { | 2750 | { |
2646 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2751 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
2647 | hda_nid_t nid = kcontrol->private_value; | 2752 | int idx = kcontrol->private_value; |
2753 | struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); | ||
2754 | hda_nid_t nid = spdif->nid; | ||
2648 | unsigned short val; | 2755 | unsigned short val; |
2649 | int change; | 2756 | int change; |
2650 | 2757 | ||
2651 | mutex_lock(&codec->spdif_mutex); | 2758 | mutex_lock(&codec->spdif_mutex); |
2652 | codec->spdif_status = ucontrol->value.iec958.status[0] | | 2759 | spdif->status = ucontrol->value.iec958.status[0] | |
2653 | ((unsigned int)ucontrol->value.iec958.status[1] << 8) | | 2760 | ((unsigned int)ucontrol->value.iec958.status[1] << 8) | |
2654 | ((unsigned int)ucontrol->value.iec958.status[2] << 16) | | 2761 | ((unsigned int)ucontrol->value.iec958.status[2] << 16) | |
2655 | ((unsigned int)ucontrol->value.iec958.status[3] << 24); | 2762 | ((unsigned int)ucontrol->value.iec958.status[3] << 24); |
2656 | val = convert_from_spdif_status(codec->spdif_status); | 2763 | val = convert_from_spdif_status(spdif->status); |
2657 | val |= codec->spdif_ctls & 1; | 2764 | val |= spdif->ctls & 1; |
2658 | change = codec->spdif_ctls != val; | 2765 | change = spdif->ctls != val; |
2659 | codec->spdif_ctls = val; | 2766 | spdif->ctls = val; |
2660 | 2767 | if (change && nid != (u16)-1) | |
2661 | if (change) | ||
2662 | set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff); | 2768 | set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff); |
2663 | |||
2664 | mutex_unlock(&codec->spdif_mutex); | 2769 | mutex_unlock(&codec->spdif_mutex); |
2665 | return change; | 2770 | return change; |
2666 | } | 2771 | } |
@@ -2671,33 +2776,42 @@ static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol, | |||
2671 | struct snd_ctl_elem_value *ucontrol) | 2776 | struct snd_ctl_elem_value *ucontrol) |
2672 | { | 2777 | { |
2673 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2778 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
2779 | int idx = kcontrol->private_value; | ||
2780 | struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); | ||
2674 | 2781 | ||
2675 | ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE; | 2782 | ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE; |
2676 | return 0; | 2783 | return 0; |
2677 | } | 2784 | } |
2678 | 2785 | ||
2786 | static inline void set_spdif_ctls(struct hda_codec *codec, hda_nid_t nid, | ||
2787 | int dig1, int dig2) | ||
2788 | { | ||
2789 | set_dig_out_convert(codec, nid, dig1, dig2); | ||
2790 | /* unmute amp switch (if any) */ | ||
2791 | if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) && | ||
2792 | (dig1 & AC_DIG1_ENABLE)) | ||
2793 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
2794 | HDA_AMP_MUTE, 0); | ||
2795 | } | ||
2796 | |||
2679 | static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, | 2797 | static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, |
2680 | struct snd_ctl_elem_value *ucontrol) | 2798 | struct snd_ctl_elem_value *ucontrol) |
2681 | { | 2799 | { |
2682 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2800 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
2683 | hda_nid_t nid = kcontrol->private_value; | 2801 | int idx = kcontrol->private_value; |
2802 | struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); | ||
2803 | hda_nid_t nid = spdif->nid; | ||
2684 | unsigned short val; | 2804 | unsigned short val; |
2685 | int change; | 2805 | int change; |
2686 | 2806 | ||
2687 | mutex_lock(&codec->spdif_mutex); | 2807 | mutex_lock(&codec->spdif_mutex); |
2688 | val = codec->spdif_ctls & ~AC_DIG1_ENABLE; | 2808 | val = spdif->ctls & ~AC_DIG1_ENABLE; |
2689 | if (ucontrol->value.integer.value[0]) | 2809 | if (ucontrol->value.integer.value[0]) |
2690 | val |= AC_DIG1_ENABLE; | 2810 | val |= AC_DIG1_ENABLE; |
2691 | change = codec->spdif_ctls != val; | 2811 | change = spdif->ctls != val; |
2692 | if (change) { | 2812 | spdif->ctls = val; |
2693 | codec->spdif_ctls = val; | 2813 | if (change && nid != (u16)-1) |
2694 | set_dig_out_convert(codec, nid, val & 0xff, -1); | 2814 | set_spdif_ctls(codec, nid, val & 0xff, -1); |
2695 | /* unmute amp switch (if any) */ | ||
2696 | if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) && | ||
2697 | (val & AC_DIG1_ENABLE)) | ||
2698 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
2699 | HDA_AMP_MUTE, 0); | ||
2700 | } | ||
2701 | mutex_unlock(&codec->spdif_mutex); | 2815 | mutex_unlock(&codec->spdif_mutex); |
2702 | return change; | 2816 | return change; |
2703 | } | 2817 | } |
@@ -2744,36 +2858,79 @@ static struct snd_kcontrol_new dig_mixes[] = { | |||
2744 | * | 2858 | * |
2745 | * Returns 0 if successful, or a negative error code. | 2859 | * Returns 0 if successful, or a negative error code. |
2746 | */ | 2860 | */ |
2747 | int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) | 2861 | int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, |
2862 | hda_nid_t associated_nid, | ||
2863 | hda_nid_t cvt_nid) | ||
2748 | { | 2864 | { |
2749 | int err; | 2865 | int err; |
2750 | struct snd_kcontrol *kctl; | 2866 | struct snd_kcontrol *kctl; |
2751 | struct snd_kcontrol_new *dig_mix; | 2867 | struct snd_kcontrol_new *dig_mix; |
2752 | int idx; | 2868 | int idx; |
2869 | struct hda_spdif_out *spdif; | ||
2753 | 2870 | ||
2754 | idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch"); | 2871 | idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch"); |
2755 | if (idx < 0) { | 2872 | if (idx < 0) { |
2756 | printk(KERN_ERR "hda_codec: too many IEC958 outputs\n"); | 2873 | printk(KERN_ERR "hda_codec: too many IEC958 outputs\n"); |
2757 | return -EBUSY; | 2874 | return -EBUSY; |
2758 | } | 2875 | } |
2876 | spdif = snd_array_new(&codec->spdif_out); | ||
2759 | for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) { | 2877 | for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) { |
2760 | kctl = snd_ctl_new1(dig_mix, codec); | 2878 | kctl = snd_ctl_new1(dig_mix, codec); |
2761 | if (!kctl) | 2879 | if (!kctl) |
2762 | return -ENOMEM; | 2880 | return -ENOMEM; |
2763 | kctl->id.index = idx; | 2881 | kctl->id.index = idx; |
2764 | kctl->private_value = nid; | 2882 | kctl->private_value = codec->spdif_out.used - 1; |
2765 | err = snd_hda_ctl_add(codec, nid, kctl); | 2883 | err = snd_hda_ctl_add(codec, associated_nid, kctl); |
2766 | if (err < 0) | 2884 | if (err < 0) |
2767 | return err; | 2885 | return err; |
2768 | } | 2886 | } |
2769 | codec->spdif_ctls = | 2887 | spdif->nid = cvt_nid; |
2770 | snd_hda_codec_read(codec, nid, 0, | 2888 | spdif->ctls = snd_hda_codec_read(codec, cvt_nid, 0, |
2771 | AC_VERB_GET_DIGI_CONVERT_1, 0); | 2889 | AC_VERB_GET_DIGI_CONVERT_1, 0); |
2772 | codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls); | 2890 | spdif->status = convert_to_spdif_status(spdif->ctls); |
2773 | return 0; | 2891 | return 0; |
2774 | } | 2892 | } |
2775 | EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls); | 2893 | EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls); |
2776 | 2894 | ||
2895 | struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec, | ||
2896 | hda_nid_t nid) | ||
2897 | { | ||
2898 | int i; | ||
2899 | for (i = 0; i < codec->spdif_out.used; i++) { | ||
2900 | struct hda_spdif_out *spdif = | ||
2901 | snd_array_elem(&codec->spdif_out, i); | ||
2902 | if (spdif->nid == nid) | ||
2903 | return spdif; | ||
2904 | } | ||
2905 | return NULL; | ||
2906 | } | ||
2907 | EXPORT_SYMBOL_HDA(snd_hda_spdif_out_of_nid); | ||
2908 | |||
2909 | void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx) | ||
2910 | { | ||
2911 | struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); | ||
2912 | |||
2913 | mutex_lock(&codec->spdif_mutex); | ||
2914 | spdif->nid = (u16)-1; | ||
2915 | mutex_unlock(&codec->spdif_mutex); | ||
2916 | } | ||
2917 | EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_unassign); | ||
2918 | |||
2919 | void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid) | ||
2920 | { | ||
2921 | struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); | ||
2922 | unsigned short val; | ||
2923 | |||
2924 | mutex_lock(&codec->spdif_mutex); | ||
2925 | if (spdif->nid != nid) { | ||
2926 | spdif->nid = nid; | ||
2927 | val = spdif->ctls; | ||
2928 | set_spdif_ctls(codec, nid, val & 0xff, (val >> 8) & 0xff); | ||
2929 | } | ||
2930 | mutex_unlock(&codec->spdif_mutex); | ||
2931 | } | ||
2932 | EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_assign); | ||
2933 | |||
2777 | /* | 2934 | /* |
2778 | * SPDIF sharing with analog output | 2935 | * SPDIF sharing with analog output |
2779 | */ | 2936 | */ |
@@ -3356,7 +3513,7 @@ static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid) | |||
3356 | * | 3513 | * |
3357 | * Returns 0 if successful, otherwise a negative error code. | 3514 | * Returns 0 if successful, otherwise a negative error code. |
3358 | */ | 3515 | */ |
3359 | static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | 3516 | int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, |
3360 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp) | 3517 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp) |
3361 | { | 3518 | { |
3362 | unsigned int i, val, wcaps; | 3519 | unsigned int i, val, wcaps; |
@@ -3448,6 +3605,7 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
3448 | 3605 | ||
3449 | return 0; | 3606 | return 0; |
3450 | } | 3607 | } |
3608 | EXPORT_SYMBOL_HDA(snd_hda_query_supported_pcm); | ||
3451 | 3609 | ||
3452 | /** | 3610 | /** |
3453 | * snd_hda_is_supported_format - Check the validity of the format | 3611 | * snd_hda_is_supported_format - Check the validity of the format |
@@ -4177,10 +4335,12 @@ EXPORT_SYMBOL_HDA(snd_hda_input_mux_put); | |||
4177 | static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, | 4335 | static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, |
4178 | unsigned int stream_tag, unsigned int format) | 4336 | unsigned int stream_tag, unsigned int format) |
4179 | { | 4337 | { |
4338 | struct hda_spdif_out *spdif = snd_hda_spdif_out_of_nid(codec, nid); | ||
4339 | |||
4180 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | 4340 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ |
4181 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) | 4341 | if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) |
4182 | set_dig_out_convert(codec, nid, | 4342 | set_dig_out_convert(codec, nid, |
4183 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff, | 4343 | spdif->ctls & ~AC_DIG1_ENABLE & 0xff, |
4184 | -1); | 4344 | -1); |
4185 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); | 4345 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); |
4186 | if (codec->slave_dig_outs) { | 4346 | if (codec->slave_dig_outs) { |
@@ -4190,9 +4350,9 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, | |||
4190 | format); | 4350 | format); |
4191 | } | 4351 | } |
4192 | /* turn on again (if needed) */ | 4352 | /* turn on again (if needed) */ |
4193 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) | 4353 | if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) |
4194 | set_dig_out_convert(codec, nid, | 4354 | set_dig_out_convert(codec, nid, |
4195 | codec->spdif_ctls & 0xff, -1); | 4355 | spdif->ctls & 0xff, -1); |
4196 | } | 4356 | } |
4197 | 4357 | ||
4198 | static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid) | 4358 | static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid) |
@@ -4348,6 +4508,8 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, | |||
4348 | { | 4508 | { |
4349 | const hda_nid_t *nids = mout->dac_nids; | 4509 | const hda_nid_t *nids = mout->dac_nids; |
4350 | int chs = substream->runtime->channels; | 4510 | int chs = substream->runtime->channels; |
4511 | struct hda_spdif_out *spdif = | ||
4512 | snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid); | ||
4351 | int i; | 4513 | int i; |
4352 | 4514 | ||
4353 | mutex_lock(&codec->spdif_mutex); | 4515 | mutex_lock(&codec->spdif_mutex); |
@@ -4356,7 +4518,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, | |||
4356 | if (chs == 2 && | 4518 | if (chs == 2 && |
4357 | snd_hda_is_supported_format(codec, mout->dig_out_nid, | 4519 | snd_hda_is_supported_format(codec, mout->dig_out_nid, |
4358 | format) && | 4520 | format) && |
4359 | !(codec->spdif_status & IEC958_AES0_NONAUDIO)) { | 4521 | !(spdif->status & IEC958_AES0_NONAUDIO)) { |
4360 | mout->dig_out_used = HDA_DIG_ANALOG_DUP; | 4522 | mout->dig_out_used = HDA_DIG_ANALOG_DUP; |
4361 | setup_dig_out_stream(codec, mout->dig_out_nid, | 4523 | setup_dig_out_stream(codec, mout->dig_out_nid, |
4362 | stream_tag, format); | 4524 | stream_tag, format); |
@@ -4528,7 +4690,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4528 | unsigned int wid_caps = get_wcaps(codec, nid); | 4690 | unsigned int wid_caps = get_wcaps(codec, nid); |
4529 | unsigned int wid_type = get_wcaps_type(wid_caps); | 4691 | unsigned int wid_type = get_wcaps_type(wid_caps); |
4530 | unsigned int def_conf; | 4692 | unsigned int def_conf; |
4531 | short assoc, loc; | 4693 | short assoc, loc, conn, dev; |
4532 | 4694 | ||
4533 | /* read all default configuration for pin complex */ | 4695 | /* read all default configuration for pin complex */ |
4534 | if (wid_type != AC_WID_PIN) | 4696 | if (wid_type != AC_WID_PIN) |
@@ -4538,10 +4700,19 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4538 | continue; | 4700 | continue; |
4539 | 4701 | ||
4540 | def_conf = snd_hda_codec_get_pincfg(codec, nid); | 4702 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
4541 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) | 4703 | conn = get_defcfg_connect(def_conf); |
4704 | if (conn == AC_JACK_PORT_NONE) | ||
4542 | continue; | 4705 | continue; |
4543 | loc = get_defcfg_location(def_conf); | 4706 | loc = get_defcfg_location(def_conf); |
4544 | switch (get_defcfg_device(def_conf)) { | 4707 | dev = get_defcfg_device(def_conf); |
4708 | |||
4709 | /* workaround for buggy BIOS setups */ | ||
4710 | if (dev == AC_JACK_LINE_OUT) { | ||
4711 | if (conn == AC_JACK_PORT_FIXED) | ||
4712 | dev = AC_JACK_SPEAKER; | ||
4713 | } | ||
4714 | |||
4715 | switch (dev) { | ||
4545 | case AC_JACK_LINE_OUT: | 4716 | case AC_JACK_LINE_OUT: |
4546 | seq = get_defcfg_sequence(def_conf); | 4717 | seq = get_defcfg_sequence(def_conf); |
4547 | assoc = get_defcfg_association(def_conf); | 4718 | assoc = get_defcfg_association(def_conf); |