|
Lines 47-56
Link Here
|
| 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 */ |
|
Lines 69-76
Link Here
|
| 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 |
|
Lines 261-267
Link Here
|
| 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; |
|
Lines 276-289
Link Here
|
| 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 |
} |
|
Lines 292-298
Link Here
|
| 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) { |
|
Lines 303-315
Link Here
|
| 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; |
|
Lines 339-344
Link Here
|
| 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; |
|
Lines 350-359
Link Here
|
| 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 */ |
|
Lines 381-400
Link Here
|
| 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; |
| 385 |
/* look for the HP-out pin */ |
396 |
/* look for the HP-out pin */ |
| 386 |
node = parse_output_jack(codec, spec, AC_JACK_HP_OUT); |
397 |
node = parse_output_jack(codec, spec, AC_JACK_HP_OUT); |
| 387 |
if (node) { |
398 |
if (node) { |
| 388 |
if (! spec->out_pin_node) |
399 |
if (! spec->out_pin_node[0]) |
| 389 |
spec->out_pin_node = node; |
400 |
spec->out_pin_node[0] = node; |
|
|
401 |
else |
| 402 |
spec->out_pin_node[1] = node; |
| 390 |
} |
403 |
} |
| 391 |
|
404 |
|
| 392 |
if (! spec->out_pin_node) { |
405 |
if (! spec->out_pin_node[0]) { |
| 393 |
/* no line-out or HP pins found, |
406 |
/* no line-out or HP pins found, |
| 394 |
* then choose for the first output pin |
407 |
* then choose for the first output pin |
| 395 |
*/ |
408 |
*/ |
| 396 |
spec->out_pin_node = parse_output_jack(codec, spec, -1); |
409 |
spec->out_pin_node[0] = parse_output_jack(codec, spec, -1); |
| 397 |
if (! spec->out_pin_node) |
410 |
if (! spec->out_pin_node[0]) |
| 398 |
snd_printd("hda_generic: no proper output path found\n"); |
411 |
snd_printd("hda_generic: no proper output path found\n"); |
| 399 |
} |
412 |
} |
| 400 |
|
413 |
|
|
Lines 505-510
Link Here
|
| 505 |
if (! (node->pin_caps & AC_PINCAP_IN)) |
518 |
if (! (node->pin_caps & AC_PINCAP_IN)) |
| 506 |
return 0; |
519 |
return 0; |
| 507 |
|
520 |
|
|
|
521 |
if (defcfg_port_conn(node) == AC_JACK_PORT_NONE) |
| 522 |
return 0; /* unconnected */ |
| 523 |
|
| 508 |
if (node->wid_caps & AC_WCAP_DIGITAL) |
524 |
if (node->wid_caps & AC_WCAP_DIGITAL) |
| 509 |
return 0; /* skip SPDIF */ |
525 |
return 0; /* skip SPDIF */ |
| 510 |
|
526 |
|
|
Lines 703-714
Link Here
|
| 703 |
static int build_output_controls(struct hda_codec *codec) |
719 |
static int build_output_controls(struct hda_codec *codec) |
| 704 |
{ |
720 |
{ |
| 705 |
struct hda_gspec *spec = codec->spec; |
721 |
struct hda_gspec *spec = codec->spec; |
| 706 |
int err; |
722 |
static const char *types[2] = { "Master", "Headphone" }; |
|
|
723 |
int i, err; |
| 707 |
|
724 |
|
| 708 |
err = create_mixer(codec, spec->pcm_vol_node, spec->pcm_vol_index, |
725 |
for (i = 0; i < 2 && spec->pcm_vol_node[i]; i++) { |
| 709 |
"PCM", "Playback"); |
726 |
err = create_mixer(codec, spec->pcm_vol_node[i], |
| 710 |
if (err < 0) |
727 |
spec->pcm_vol_index[i], |
| 711 |
return err; |
728 |
types[i], "Playback"); |
|
|
729 |
if (err < 0) |
| 730 |
return err; |
| 731 |
} |
| 712 |
return 0; |
732 |
return 0; |
| 713 |
} |
733 |
} |
| 714 |
|
734 |
|
|
Lines 805-811
Link Here
|
| 805 |
int err; |
825 |
int err; |
| 806 |
const char *type; |
826 |
const char *type; |
| 807 |
|
827 |
|
| 808 |
if (! spec->out_pin_node) |
828 |
if (! spec->out_pin_node[0]) |
| 809 |
return 0; |
829 |
return 0; |
| 810 |
|
830 |
|
| 811 |
list_for_each(p, &spec->nid_list) { |
831 |
list_for_each(p, &spec->nid_list) { |
|
Lines 820-826
Link Here
|
| 820 |
if (check_existing_control(codec, type, "Playback")) |
840 |
if (check_existing_control(codec, type, "Playback")) |
| 821 |
continue; |
841 |
continue; |
| 822 |
clear_check_flags(spec); |
842 |
clear_check_flags(spec); |
| 823 |
err = parse_loopback_path(codec, spec, spec->out_pin_node, |
843 |
err = parse_loopback_path(codec, spec, |
|
|
844 |
spec->out_pin_node[0], |
| 824 |
node, type); |
845 |
node, type); |
| 825 |
if (err < 0) |
846 |
if (err < 0) |
| 826 |
return err; |
847 |
return err; |
|
Lines 855-866
Link Here
|
| 855 |
.channels_max = 2, |
876 |
.channels_max = 2, |
| 856 |
}; |
877 |
}; |
| 857 |
|
878 |
|
|
|
879 |
static int generic_pcm2_prepare(struct hda_pcm_stream *hinfo, |
| 880 |
struct hda_codec *codec, |
| 881 |
unsigned int stream_tag, |
| 882 |
unsigned int format, |
| 883 |
struct snd_pcm_substream *substream) |
| 884 |
{ |
| 885 |
struct hda_gspec *spec = codec->spec; |
| 886 |
|
| 887 |
snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format); |
| 888 |
snd_hda_codec_setup_stream(codec, spec->dac_node[1]->nid, |
| 889 |
stream_tag, 0, format); |
| 890 |
return 0; |
| 891 |
} |
| 892 |
|
| 893 |
static int generic_pcm2_cleanup(struct hda_pcm_stream *hinfo, |
| 894 |
struct hda_codec *codec, |
| 895 |
struct snd_pcm_substream *substream) |
| 896 |
{ |
| 897 |
struct hda_gspec *spec = codec->spec; |
| 898 |
|
| 899 |
snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0); |
| 900 |
snd_hda_codec_setup_stream(codec, spec->dac_node[1]->nid, 0, 0, 0); |
| 901 |
return 0; |
| 902 |
} |
| 903 |
|
| 858 |
static int build_generic_pcms(struct hda_codec *codec) |
904 |
static int build_generic_pcms(struct hda_codec *codec) |
| 859 |
{ |
905 |
{ |
| 860 |
struct hda_gspec *spec = codec->spec; |
906 |
struct hda_gspec *spec = codec->spec; |
| 861 |
struct hda_pcm *info = &spec->pcm_rec; |
907 |
struct hda_pcm *info = &spec->pcm_rec; |
| 862 |
|
908 |
|
| 863 |
if (! spec->dac_node && ! spec->adc_node) { |
909 |
if (! spec->dac_node[0] && ! spec->adc_node) { |
| 864 |
snd_printd("hda_generic: no PCM found\n"); |
910 |
snd_printd("hda_generic: no PCM found\n"); |
| 865 |
return 0; |
911 |
return 0; |
| 866 |
} |
912 |
} |
|
Lines 869-877
Link Here
|
| 869 |
codec->pcm_info = info; |
915 |
codec->pcm_info = info; |
| 870 |
|
916 |
|
| 871 |
info->name = "HDA Generic"; |
917 |
info->name = "HDA Generic"; |
| 872 |
if (spec->dac_node) { |
918 |
if (spec->dac_node[0]) { |
| 873 |
info->stream[0] = generic_pcm_playback; |
919 |
info->stream[0] = generic_pcm_playback; |
| 874 |
info->stream[0].nid = spec->dac_node->nid; |
920 |
info->stream[0].nid = spec->dac_node[0]->nid; |
|
|
921 |
if (spec->dac_node[1]) { |
| 922 |
info->stream[0].ops.prepare = generic_pcm2_prepare; |
| 923 |
info->stream[0].ops.cleanup = generic_pcm2_cleanup; |
| 924 |
} |
| 875 |
} |
925 |
} |
| 876 |
if (spec->adc_node) { |
926 |
if (spec->adc_node) { |
| 877 |
info->stream[1] = generic_pcm_playback; |
927 |
info->stream[1] = generic_pcm_playback; |