diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 73 |
1 files changed, 52 insertions, 21 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index b575c9989f3c..655bd23e80df 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -3276,15 +3276,6 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, | |||
3276 | return -1; | 3276 | return -1; |
3277 | } | 3277 | } |
3278 | 3278 | ||
3279 | static int has_multi_connection(struct hda_codec *codec, hda_nid_t mux) | ||
3280 | { | ||
3281 | hda_nid_t conn[HDA_MAX_NUM_INPUTS]; | ||
3282 | int nums; | ||
3283 | |||
3284 | nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn)); | ||
3285 | return nums > 1; | ||
3286 | } | ||
3287 | |||
3288 | /* get an unassigned DAC from the given list. | 3279 | /* get an unassigned DAC from the given list. |
3289 | * Return the nid if found and reduce the DAC list, or return zero if | 3280 | * Return the nid if found and reduce the DAC list, or return zero if |
3290 | * not found | 3281 | * not found |
@@ -3455,6 +3446,51 @@ static int cx_auto_mux_enum_get(struct snd_kcontrol *kcontrol, | |||
3455 | return 0; | 3446 | return 0; |
3456 | } | 3447 | } |
3457 | 3448 | ||
3449 | /* look for the route the given pin from mux and return the index; | ||
3450 | * if do_select is set, actually select the route. | ||
3451 | */ | ||
3452 | static int __select_input_connection(struct hda_codec *codec, hda_nid_t mux, | ||
3453 | hda_nid_t pin, bool do_select, int depth) | ||
3454 | { | ||
3455 | hda_nid_t conn[HDA_MAX_NUM_INPUTS]; | ||
3456 | int i, nums; | ||
3457 | |||
3458 | nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn)); | ||
3459 | for (i = 0; i < nums; i++) | ||
3460 | if (conn[i] == pin) { | ||
3461 | if (do_select) | ||
3462 | snd_hda_codec_write(codec, mux, 0, | ||
3463 | AC_VERB_SET_CONNECT_SEL, i); | ||
3464 | return i; | ||
3465 | } | ||
3466 | depth++; | ||
3467 | if (depth == 2) | ||
3468 | return -1; | ||
3469 | for (i = 0; i < nums; i++) { | ||
3470 | int ret = __select_input_connection(codec, conn[i], pin, | ||
3471 | do_select, depth); | ||
3472 | if (ret >= 0) { | ||
3473 | if (do_select) | ||
3474 | snd_hda_codec_write(codec, mux, 0, | ||
3475 | AC_VERB_SET_CONNECT_SEL, i); | ||
3476 | return ret; | ||
3477 | } | ||
3478 | } | ||
3479 | return -1; | ||
3480 | } | ||
3481 | |||
3482 | static void select_input_connection(struct hda_codec *codec, hda_nid_t mux, | ||
3483 | hda_nid_t pin) | ||
3484 | { | ||
3485 | __select_input_connection(codec, mux, pin, true, 0); | ||
3486 | } | ||
3487 | |||
3488 | static int get_input_connection(struct hda_codec *codec, hda_nid_t mux, | ||
3489 | hda_nid_t pin) | ||
3490 | { | ||
3491 | return __select_input_connection(codec, mux, pin, false, 0); | ||
3492 | } | ||
3493 | |||
3458 | static int cx_auto_mux_enum_update(struct hda_codec *codec, | 3494 | static int cx_auto_mux_enum_update(struct hda_codec *codec, |
3459 | const struct hda_input_mux *imux, | 3495 | const struct hda_input_mux *imux, |
3460 | unsigned int idx) | 3496 | unsigned int idx) |
@@ -3469,10 +3505,8 @@ static int cx_auto_mux_enum_update(struct hda_codec *codec, | |||
3469 | if (spec->cur_mux[0] == idx) | 3505 | if (spec->cur_mux[0] == idx) |
3470 | return 0; | 3506 | return 0; |
3471 | adc = spec->imux_adcs[idx]; | 3507 | adc = spec->imux_adcs[idx]; |
3472 | if (has_multi_connection(codec, adc)) | 3508 | select_input_connection(codec, spec->imux_adcs[idx], |
3473 | snd_hda_codec_write(codec, adc, 0, | 3509 | spec->imux_pins[idx]); |
3474 | AC_VERB_SET_CONNECT_SEL, | ||
3475 | imux->items[idx].index); | ||
3476 | if (spec->cur_adc && spec->cur_adc != adc) { | 3510 | if (spec->cur_adc && spec->cur_adc != adc) { |
3477 | /* stream is running, let's swap the current ADC */ | 3511 | /* stream is running, let's swap the current ADC */ |
3478 | __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1); | 3512 | __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1); |
@@ -3584,8 +3618,8 @@ static void cx_auto_parse_input(struct hda_codec *codec) | |||
3584 | for (i = 0; i < cfg->num_inputs; i++) { | 3618 | for (i = 0; i < cfg->num_inputs; i++) { |
3585 | for (j = 0; j < spec->num_adc_nids; j++) { | 3619 | for (j = 0; j < spec->num_adc_nids; j++) { |
3586 | hda_nid_t adc = spec->adc_nids[j]; | 3620 | hda_nid_t adc = spec->adc_nids[j]; |
3587 | int idx = get_connection_index(codec, adc, | 3621 | int idx = get_input_connection(codec, adc, |
3588 | cfg->inputs[i].pin); | 3622 | cfg->inputs[i].pin); |
3589 | if (idx >= 0) { | 3623 | if (idx >= 0) { |
3590 | const char *label; | 3624 | const char *label; |
3591 | label = hda_get_autocfg_input_label(codec, cfg, i); | 3625 | label = hda_get_autocfg_input_label(codec, cfg, i); |
@@ -3791,11 +3825,8 @@ static void cx_auto_init_input(struct hda_codec *codec) | |||
3791 | AC_USRSP_EN | CONEXANT_MIC_EVENT); | 3825 | AC_USRSP_EN | CONEXANT_MIC_EVENT); |
3792 | cx_auto_automic(codec); | 3826 | cx_auto_automic(codec); |
3793 | } else { | 3827 | } else { |
3794 | for (i = 0; i < spec->num_adc_nids; i++) { | 3828 | select_input_connection(codec, spec->imux_adcs[0], |
3795 | snd_hda_codec_write(codec, spec->adc_nids[i], 0, | 3829 | spec->imux_pins[0]); |
3796 | AC_VERB_SET_CONNECT_SEL, | ||
3797 | spec->private_imux.items[0].index); | ||
3798 | } | ||
3799 | } | 3830 | } |
3800 | } | 3831 | } |
3801 | 3832 | ||
@@ -3924,7 +3955,7 @@ static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid, | |||
3924 | 3955 | ||
3925 | for (i = 0; i < spec->num_adc_nids; i++) { | 3956 | for (i = 0; i < spec->num_adc_nids; i++) { |
3926 | hda_nid_t adc_nid = spec->adc_nids[i]; | 3957 | hda_nid_t adc_nid = spec->adc_nids[i]; |
3927 | int idx = get_connection_index(codec, adc_nid, nid); | 3958 | int idx = get_input_connection(codec, adc_nid, nid); |
3928 | if (idx < 0) | 3959 | if (idx < 0) |
3929 | continue; | 3960 | continue; |
3930 | return cx_auto_add_volume_idx(codec, label, pfx, | 3961 | return cx_auto_add_volume_idx(codec, label, pfx, |