aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2006-03-21 05:29:07 -0500
committerJaroslav Kysela <perex@suse.cz>2006-03-22 04:40:49 -0500
commit97ec558a88fb03fa23aee0832a88964e76e4a4db (patch)
tree406aecd3632ae51d946a13509482cf75bf66b822 /sound
parent82bc955f6379135e6ce35ff90c7ac411fd412c4c (diff)
[ALSA] hda-codec - Fix generic auto-configurator
Modules: HDA generic driver Fixed the generic auto-configurator to check speaker pins in addition. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_generic.c128
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 */
49struct hda_gspec { 49struct 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 */
263static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, 267static 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
703static int build_output_controls(struct hda_codec *codec) 725static 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
885static 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
899static 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
858static int build_generic_pcms(struct hda_codec *codec) 910static 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;