diff options
| -rw-r--r-- | sound/pci/hda/hda_generic.c | 128 |
1 files changed, 92 insertions, 36 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 39edfcfd3abd..85ad164ada59 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
| @@ -47,10 +47,10 @@ struct hda_gnode { | |||
| 47 | 47 | ||
| 48 | /* patch-specific record */ | 48 | /* patch-specific record */ |
| 49 | struct hda_gspec { | 49 | struct hda_gspec { |
| 50 | struct hda_gnode *dac_node; /* DAC node */ | 50 | struct hda_gnode *dac_node[2]; /* DAC node */ |
| 51 | struct hda_gnode *out_pin_node; /* Output pin (Line-Out) node */ | 51 | struct hda_gnode *out_pin_node[2]; /* Output pin (Line-Out) node */ |
| 52 | struct hda_gnode *pcm_vol_node; /* Node for PCM volume */ | 52 | struct hda_gnode *pcm_vol_node[2]; /* Node for PCM volume */ |
| 53 | unsigned int pcm_vol_index; /* connection of PCM volume */ | 53 | unsigned int pcm_vol_index[2]; /* connection of PCM volume */ |
| 54 | 54 | ||
| 55 | struct hda_gnode *adc_node; /* ADC node */ | 55 | struct hda_gnode *adc_node; /* ADC node */ |
| 56 | struct hda_gnode *cap_vol_node; /* Node for capture volume */ | 56 | struct hda_gnode *cap_vol_node; /* Node for capture volume */ |
| @@ -69,8 +69,12 @@ struct hda_gspec { | |||
| 69 | /* | 69 | /* |
| 70 | * retrieve the default device type from the default config value | 70 | * retrieve the default device type from the default config value |
| 71 | */ | 71 | */ |
| 72 | #define defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) | 72 | #define defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> \ |
| 73 | #define defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) | 73 | AC_DEFCFG_DEVICE_SHIFT) |
| 74 | #define defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> \ | ||
| 75 | AC_DEFCFG_LOCATION_SHIFT) | ||
| 76 | #define defcfg_port_conn(node) (((node)->def_cfg & AC_DEFCFG_PORT_CONN) >> \ | ||
| 77 | AC_DEFCFG_PORT_CONN_SHIFT) | ||
| 74 | 78 | ||
| 75 | /* | 79 | /* |
| 76 | * destructor | 80 | * destructor |
| @@ -261,7 +265,7 @@ static void clear_check_flags(struct hda_gspec *spec) | |||
| 261 | * returns 0 if not found, 1 if found, or a negative error code. | 265 | * returns 0 if not found, 1 if found, or a negative error code. |
| 262 | */ | 266 | */ |
| 263 | static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, | 267 | static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, |
| 264 | struct hda_gnode *node) | 268 | struct hda_gnode *node, int dac_idx) |
| 265 | { | 269 | { |
| 266 | int i, err; | 270 | int i, err; |
| 267 | struct hda_gnode *child; | 271 | struct hda_gnode *child; |
| @@ -276,14 +280,14 @@ static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, | |||
| 276 | return 0; | 280 | return 0; |
| 277 | } | 281 | } |
| 278 | snd_printdd("AUD_OUT found %x\n", node->nid); | 282 | snd_printdd("AUD_OUT found %x\n", node->nid); |
| 279 | if (spec->dac_node) { | 283 | if (spec->dac_node[dac_idx]) { |
| 280 | /* already DAC node is assigned, just unmute & connect */ | 284 | /* already DAC node is assigned, just unmute & connect */ |
| 281 | return node == spec->dac_node; | 285 | return node == spec->dac_node[dac_idx]; |
| 282 | } | 286 | } |
| 283 | spec->dac_node = node; | 287 | spec->dac_node[dac_idx] = node; |
| 284 | if (node->wid_caps & AC_WCAP_OUT_AMP) { | 288 | if (node->wid_caps & AC_WCAP_OUT_AMP) { |
| 285 | spec->pcm_vol_node = node; | 289 | spec->pcm_vol_node[dac_idx] = node; |
| 286 | spec->pcm_vol_index = 0; | 290 | spec->pcm_vol_index[dac_idx] = 0; |
| 287 | } | 291 | } |
| 288 | return 1; /* found */ | 292 | return 1; /* found */ |
| 289 | } | 293 | } |
| @@ -292,7 +296,7 @@ static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, | |||
| 292 | child = hda_get_node(spec, node->conn_list[i]); | 296 | child = hda_get_node(spec, node->conn_list[i]); |
| 293 | if (! child) | 297 | if (! child) |
| 294 | continue; | 298 | continue; |
| 295 | err = parse_output_path(codec, spec, child); | 299 | err = parse_output_path(codec, spec, child, dac_idx); |
| 296 | if (err < 0) | 300 | if (err < 0) |
| 297 | return err; | 301 | return err; |
| 298 | else if (err > 0) { | 302 | else if (err > 0) { |
| @@ -303,13 +307,13 @@ static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, | |||
| 303 | select_input_connection(codec, node, i); | 307 | select_input_connection(codec, node, i); |
| 304 | unmute_input(codec, node, i); | 308 | unmute_input(codec, node, i); |
| 305 | unmute_output(codec, node); | 309 | unmute_output(codec, node); |
| 306 | if (! spec->pcm_vol_node) { | 310 | if (! spec->pcm_vol_node[dac_idx]) { |
| 307 | if (node->wid_caps & AC_WCAP_IN_AMP) { | 311 | if (node->wid_caps & AC_WCAP_IN_AMP) { |
| 308 | spec->pcm_vol_node = node; | 312 | spec->pcm_vol_node[dac_idx] = node; |
| 309 | spec->pcm_vol_index = i; | 313 | spec->pcm_vol_index[dac_idx] = i; |
| 310 | } else if (node->wid_caps & AC_WCAP_OUT_AMP) { | 314 | } else if (node->wid_caps & AC_WCAP_OUT_AMP) { |
| 311 | spec->pcm_vol_node = node; | 315 | spec->pcm_vol_node[dac_idx] = node; |
| 312 | spec->pcm_vol_index = 0; | 316 | spec->pcm_vol_index[dac_idx] = 0; |
| 313 | } | 317 | } |
| 314 | } | 318 | } |
| 315 | return 1; | 319 | return 1; |
| @@ -339,6 +343,8 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec, | |||
| 339 | /* output capable? */ | 343 | /* output capable? */ |
| 340 | if (! (node->pin_caps & AC_PINCAP_OUT)) | 344 | if (! (node->pin_caps & AC_PINCAP_OUT)) |
| 341 | continue; | 345 | continue; |
| 346 | if (defcfg_port_conn(node) == AC_JACK_PORT_NONE) | ||
| 347 | continue; /* unconnected */ | ||
| 342 | if (jack_type >= 0) { | 348 | if (jack_type >= 0) { |
| 343 | if (jack_type != defcfg_type(node)) | 349 | if (jack_type != defcfg_type(node)) |
| 344 | continue; | 350 | continue; |
| @@ -350,10 +356,15 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec, | |||
| 350 | continue; | 356 | continue; |
| 351 | } | 357 | } |
| 352 | clear_check_flags(spec); | 358 | clear_check_flags(spec); |
| 353 | err = parse_output_path(codec, spec, node); | 359 | err = parse_output_path(codec, spec, node, 0); |
| 354 | if (err < 0) | 360 | if (err < 0) |
| 355 | return NULL; | 361 | return NULL; |
| 356 | else if (err > 0) { | 362 | if (! err && spec->out_pin_node[0]) { |
| 363 | err = parse_output_path(codec, spec, node, 1); | ||
| 364 | if (err < 0) | ||
| 365 | return NULL; | ||
| 366 | } | ||
| 367 | if (err > 0) { | ||
| 357 | /* unmute the PIN output */ | 368 | /* unmute the PIN output */ |
| 358 | unmute_output(codec, node); | 369 | unmute_output(codec, node); |
| 359 | /* set PIN-Out enable */ | 370 | /* set PIN-Out enable */ |
| @@ -381,20 +392,28 @@ static int parse_output(struct hda_codec *codec) | |||
| 381 | /* first, look for the line-out pin */ | 392 | /* first, look for the line-out pin */ |
| 382 | node = parse_output_jack(codec, spec, AC_JACK_LINE_OUT); | 393 | node = parse_output_jack(codec, spec, AC_JACK_LINE_OUT); |
| 383 | if (node) /* found, remember the PIN node */ | 394 | if (node) /* found, remember the PIN node */ |
| 384 | spec->out_pin_node = node; | 395 | spec->out_pin_node[0] = node; |
| 396 | else { | ||
| 397 | /* if no line-out is found, try speaker out */ | ||
| 398 | node = parse_output_jack(codec, spec, AC_JACK_SPEAKER); | ||
| 399 | if (node) | ||
| 400 | spec->out_pin_node[0] = node; | ||
| 401 | } | ||
| 385 | /* look for the HP-out pin */ | 402 | /* look for the HP-out pin */ |
| 386 | node = parse_output_jack(codec, spec, AC_JACK_HP_OUT); | 403 | node = parse_output_jack(codec, spec, AC_JACK_HP_OUT); |
| 387 | if (node) { | 404 | if (node) { |
| 388 | if (! spec->out_pin_node) | 405 | if (! spec->out_pin_node[0]) |
| 389 | spec->out_pin_node = node; | 406 | spec->out_pin_node[0] = node; |
| 407 | else | ||
| 408 | spec->out_pin_node[1] = node; | ||
| 390 | } | 409 | } |
| 391 | 410 | ||
| 392 | if (! spec->out_pin_node) { | 411 | if (! spec->out_pin_node[0]) { |
| 393 | /* no line-out or HP pins found, | 412 | /* no line-out or HP pins found, |
| 394 | * then choose for the first output pin | 413 | * then choose for the first output pin |
| 395 | */ | 414 | */ |
| 396 | spec->out_pin_node = parse_output_jack(codec, spec, -1); | 415 | spec->out_pin_node[0] = parse_output_jack(codec, spec, -1); |
| 397 | if (! spec->out_pin_node) | 416 | if (! spec->out_pin_node[0]) |
| 398 | snd_printd("hda_generic: no proper output path found\n"); | 417 | snd_printd("hda_generic: no proper output path found\n"); |
| 399 | } | 418 | } |
| 400 | 419 | ||
| @@ -505,6 +524,9 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, | |||
| 505 | if (! (node->pin_caps & AC_PINCAP_IN)) | 524 | if (! (node->pin_caps & AC_PINCAP_IN)) |
| 506 | return 0; | 525 | return 0; |
| 507 | 526 | ||
| 527 | if (defcfg_port_conn(node) == AC_JACK_PORT_NONE) | ||
| 528 | return 0; /* unconnected */ | ||
| 529 | |||
| 508 | if (node->wid_caps & AC_WCAP_DIGITAL) | 530 | if (node->wid_caps & AC_WCAP_DIGITAL) |
| 509 | return 0; /* skip SPDIF */ | 531 | return 0; /* skip SPDIF */ |
| 510 | 532 | ||
| @@ -703,12 +725,16 @@ static int check_existing_control(struct hda_codec *codec, const char *type, con | |||
| 703 | static int build_output_controls(struct hda_codec *codec) | 725 | static int build_output_controls(struct hda_codec *codec) |
| 704 | { | 726 | { |
| 705 | struct hda_gspec *spec = codec->spec; | 727 | struct hda_gspec *spec = codec->spec; |
| 706 | int err; | 728 | static const char *types[2] = { "Master", "Headphone" }; |
| 729 | int i, err; | ||
| 707 | 730 | ||
| 708 | err = create_mixer(codec, spec->pcm_vol_node, spec->pcm_vol_index, | 731 | for (i = 0; i < 2 && spec->pcm_vol_node[i]; i++) { |
| 709 | "PCM", "Playback"); | 732 | err = create_mixer(codec, spec->pcm_vol_node[i], |
| 710 | if (err < 0) | 733 | spec->pcm_vol_index[i], |
| 711 | return err; | 734 | types[i], "Playback"); |
| 735 | if (err < 0) | ||
| 736 | return err; | ||
| 737 | } | ||
| 712 | return 0; | 738 | return 0; |
| 713 | } | 739 | } |
| 714 | 740 | ||
| @@ -805,7 +831,7 @@ static int build_loopback_controls(struct hda_codec *codec) | |||
| 805 | int err; | 831 | int err; |
| 806 | const char *type; | 832 | const char *type; |
| 807 | 833 | ||
| 808 | if (! spec->out_pin_node) | 834 | if (! spec->out_pin_node[0]) |
| 809 | return 0; | 835 | return 0; |
| 810 | 836 | ||
| 811 | list_for_each(p, &spec->nid_list) { | 837 | list_for_each(p, &spec->nid_list) { |
| @@ -820,7 +846,8 @@ static int build_loopback_controls(struct hda_codec *codec) | |||
| 820 | if (check_existing_control(codec, type, "Playback")) | 846 | if (check_existing_control(codec, type, "Playback")) |
| 821 | continue; | 847 | continue; |
| 822 | clear_check_flags(spec); | 848 | clear_check_flags(spec); |
| 823 | err = parse_loopback_path(codec, spec, spec->out_pin_node, | 849 | err = parse_loopback_path(codec, spec, |
| 850 | spec->out_pin_node[0], | ||
| 824 | node, type); | 851 | node, type); |
| 825 | if (err < 0) | 852 | if (err < 0) |
| 826 | return err; | 853 | return err; |
| @@ -855,12 +882,37 @@ static struct hda_pcm_stream generic_pcm_playback = { | |||
| 855 | .channels_max = 2, | 882 | .channels_max = 2, |
| 856 | }; | 883 | }; |
| 857 | 884 | ||
| 885 | static int generic_pcm2_prepare(struct hda_pcm_stream *hinfo, | ||
| 886 | struct hda_codec *codec, | ||
| 887 | unsigned int stream_tag, | ||
| 888 | unsigned int format, | ||
| 889 | struct snd_pcm_substream *substream) | ||
| 890 | { | ||
| 891 | struct hda_gspec *spec = codec->spec; | ||
| 892 | |||
| 893 | snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format); | ||
| 894 | snd_hda_codec_setup_stream(codec, spec->dac_node[1]->nid, | ||
| 895 | stream_tag, 0, format); | ||
| 896 | return 0; | ||
| 897 | } | ||
| 898 | |||
| 899 | static int generic_pcm2_cleanup(struct hda_pcm_stream *hinfo, | ||
| 900 | struct hda_codec *codec, | ||
| 901 | struct snd_pcm_substream *substream) | ||
| 902 | { | ||
| 903 | struct hda_gspec *spec = codec->spec; | ||
| 904 | |||
| 905 | snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0); | ||
| 906 | snd_hda_codec_setup_stream(codec, spec->dac_node[1]->nid, 0, 0, 0); | ||
| 907 | return 0; | ||
| 908 | } | ||
| 909 | |||
| 858 | static int build_generic_pcms(struct hda_codec *codec) | 910 | static int build_generic_pcms(struct hda_codec *codec) |
| 859 | { | 911 | { |
| 860 | struct hda_gspec *spec = codec->spec; | 912 | struct hda_gspec *spec = codec->spec; |
| 861 | struct hda_pcm *info = &spec->pcm_rec; | 913 | struct hda_pcm *info = &spec->pcm_rec; |
| 862 | 914 | ||
| 863 | if (! spec->dac_node && ! spec->adc_node) { | 915 | if (! spec->dac_node[0] && ! spec->adc_node) { |
| 864 | snd_printd("hda_generic: no PCM found\n"); | 916 | snd_printd("hda_generic: no PCM found\n"); |
| 865 | return 0; | 917 | return 0; |
| 866 | } | 918 | } |
| @@ -869,9 +921,13 @@ static int build_generic_pcms(struct hda_codec *codec) | |||
| 869 | codec->pcm_info = info; | 921 | codec->pcm_info = info; |
| 870 | 922 | ||
| 871 | info->name = "HDA Generic"; | 923 | info->name = "HDA Generic"; |
| 872 | if (spec->dac_node) { | 924 | if (spec->dac_node[0]) { |
| 873 | info->stream[0] = generic_pcm_playback; | 925 | info->stream[0] = generic_pcm_playback; |
| 874 | info->stream[0].nid = spec->dac_node->nid; | 926 | info->stream[0].nid = spec->dac_node[0]->nid; |
| 927 | if (spec->dac_node[1]) { | ||
| 928 | info->stream[0].ops.prepare = generic_pcm2_prepare; | ||
| 929 | info->stream[0].ops.cleanup = generic_pcm2_cleanup; | ||
| 930 | } | ||
| 875 | } | 931 | } |
| 876 | if (spec->adc_node) { | 932 | if (spec->adc_node) { |
| 877 | info->stream[1] = generic_pcm_playback; | 933 | info->stream[1] = generic_pcm_playback; |
