diff options
| -rw-r--r-- | sound/pci/ctxfi/ctatc.c | 33 | ||||
| -rw-r--r-- | sound/pci/ctxfi/ctatc.h | 4 | ||||
| -rw-r--r-- | sound/pci/ctxfi/ctdaio.c | 2 | ||||
| -rw-r--r-- | sound/pci/ctxfi/ctdaio.h | 1 | ||||
| -rw-r--r-- | sound/pci/ctxfi/cthardware.h | 1 | ||||
| -rw-r--r-- | sound/pci/ctxfi/cthw20k1.c | 1 | ||||
| -rw-r--r-- | sound/pci/ctxfi/cthw20k2.c | 1 | ||||
| -rw-r--r-- | sound/pci/ctxfi/ctmixer.c | 73 |
8 files changed, 111 insertions, 5 deletions
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index ce2b16722118..ff3694b3021e 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -987,6 +987,24 @@ static struct capabilities atc_capabilities(struct ct_atc *atc) return hw->capabilities(hw); } +static void atc_dedicated_rca_select(struct ct_atc *atc) +{ + struct dao *dao; + struct ct_mixer *mixer = atc->mixer; + struct rsc *rscs[2] = {NULL}; + + dao = container_of(atc->daios[atc->rca_state ? RCA : LINEO1], + struct dao, daio); + dao->ops->clear_left_input(dao); + dao->ops->clear_right_input(dao); + + mixer->get_output_ports(mixer, MIX_WAVE_FRONT, &rscs[0], &rscs[1]); + dao = container_of(atc->daios[atc->rca_state ? LINEO1 : RCA], + struct dao, daio); + dao->ops->set_left_input(dao, rscs[0]); + dao->ops->set_right_input(dao, rscs[1]); +} + static int atc_output_switch_get(struct ct_atc *atc) { struct hw *hw = atc->hw; @@ -1088,6 +1106,11 @@ static int atc_mic_unmute(struct ct_atc *atc, unsigned char state) return atc_daio_unmute(atc, state, MIC); } +static int atc_rca_unmute(struct ct_atc *atc, unsigned char state) +{ + return atc_daio_unmute(atc, state, RCA); +} + static int atc_spdif_out_unmute(struct ct_atc *atc, unsigned char state) { return atc_daio_unmute(atc, state, SPDIFOO); @@ -1303,6 +1326,7 @@ static int atc_identify_card(struct ct_atc *atc, unsigned int ssid) dev_info(atc->card->dev, "chip %s model %s (%04x:%04x) is found\n", atc->chip_name, atc->model_name, vendor_id, device_id); + atc->rca_state = 0; return 0; } @@ -1400,11 +1424,11 @@ static int atc_get_resources(struct ct_atc *atc) daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO]; da_desc.msr = atc->msr; for (i = 0; i < NUM_DAIOTYP; i++) { - if ((i == MIC) && !cap.dedicated_mic) + if (((i == MIC) && !cap.dedicated_mic) || ((i == RCA) && !cap.dedicated_rca)) continue; da_desc.type = (atc->model != CTSB073X) ? i : ((i == SPDIFIO) ? SPDIFI1 : i); - da_desc.output = i < LINEIM; + da_desc.output = (i < LINEIM) || (i == RCA); err = daio_mgr->get_daio(daio_mgr, &da_desc, (struct daio **)&atc->daios[i]); if (err) { @@ -1511,6 +1535,9 @@ static void atc_connect_resources(struct ct_atc *atc) dao->ops->set_right_input(dao, rscs[1]); } + if (cap.dedicated_rca) + atc_dedicated_rca_select(atc); + dai = container_of(atc->daios[LINEIM], struct dai, daio); atc_connect_dai(atc->rsc_mgrs[SRC], dai, (struct src **)&atc->srcs[2], @@ -1643,12 +1670,14 @@ static const struct ct_atc atc_preset = { .line_rear_unmute = atc_line_rear_unmute, .line_in_unmute = atc_line_in_unmute, .mic_unmute = atc_mic_unmute, + .rca_unmute = atc_rca_unmute, .spdif_out_unmute = atc_spdif_out_unmute, .spdif_in_unmute = atc_spdif_in_unmute, .spdif_out_get_status = atc_spdif_out_get_status, .spdif_out_set_status = atc_spdif_out_set_status, .spdif_out_passthru = atc_spdif_out_passthru, .capabilities = atc_capabilities, + .dedicated_rca_select = atc_dedicated_rca_select, .output_switch_get = atc_output_switch_get, .output_switch_put = atc_output_switch_put, .mic_source_switch_get = atc_mic_source_switch_get, diff --git a/sound/pci/ctxfi/ctatc.h b/sound/pci/ctxfi/ctatc.h index 671edc46bd50..ca0a9d5b86d8 100644 --- a/sound/pci/ctxfi/ctatc.h +++ b/sound/pci/ctxfi/ctatc.h @@ -82,6 +82,8 @@ struct ct_atc { const char *chip_name; const char *model_name; + unsigned char rca_state; /* 0 = dedicated RCA, 1 = 7.1ch Front */ + struct ct_vm *vm; /* device virtual memory manager for this card */ int (*map_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm); void (*unmap_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm); @@ -113,12 +115,14 @@ struct ct_atc { int (*line_rear_unmute)(struct ct_atc *atc, unsigned char state); int (*line_in_unmute)(struct ct_atc *atc, unsigned char state); int (*mic_unmute)(struct ct_atc *atc, unsigned char state); + int (*rca_unmute)(struct ct_atc *atc, unsigned char state); int (*spdif_out_unmute)(struct ct_atc *atc, unsigned char state); int (*spdif_in_unmute)(struct ct_atc *atc, unsigned char state); int (*spdif_out_get_status)(struct ct_atc *atc, unsigned int *status); int (*spdif_out_set_status)(struct ct_atc *atc, unsigned int status); int (*spdif_out_passthru)(struct ct_atc *atc, unsigned char state); struct capabilities (*capabilities)(struct ct_atc *atc); + void (*dedicated_rca_select)(struct ct_atc *atc); int (*output_switch_get)(struct ct_atc *atc); int (*output_switch_put)(struct ct_atc *atc, int position); int (*mic_source_switch_get)(struct ct_atc *atc); diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c index f012d47689d1..1c8f8efd836c 100644 --- a/sound/pci/ctxfi/ctdaio.c +++ b/sound/pci/ctxfi/ctdaio.c @@ -45,6 +45,7 @@ static const struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = { [LINEO4] = {.left = 0x70, .right = 0x71}, [LINEIM] = {.left = 0x45, .right = 0xc5}, [MIC] = {.left = 0x55, .right = 0xd5}, + [RCA] = {.left = 0x30, .right = 0x31}, [SPDIFOO] = {.left = 0x00, .right = 0x01}, [SPDIFIO] = {.left = 0x05, .right = 0x85}, }; @@ -123,6 +124,7 @@ static unsigned int daio_device_index(enum DAIOTYP type, struct hw *hw) case LINEO4: return 6; case LINEIM: return 4; case MIC: return 5; + case RCA: return 3; default: return -EINVAL; } default: diff --git a/sound/pci/ctxfi/ctdaio.h b/sound/pci/ctxfi/ctdaio.h index b337da2de8b5..99d55f19e3ca 100644 --- a/sound/pci/ctxfi/ctdaio.h +++ b/sound/pci/ctxfi/ctdaio.h @@ -31,6 +31,7 @@ enum DAIOTYP { LINEIM, SPDIFIO, /* S/PDIF In (Flexijack/Optical) on the card */ MIC, /* Dedicated mic on Titanium HD */ + RCA, SPDIFI1, /* S/PDIF In on internal Drive Bay */ NUM_DAIOTYP }; diff --git a/sound/pci/ctxfi/cthardware.h b/sound/pci/ctxfi/cthardware.h index d29b4e5b3fcc..84ea690763e7 100644 --- a/sound/pci/ctxfi/cthardware.h +++ b/sound/pci/ctxfi/cthardware.h @@ -62,6 +62,7 @@ struct card_conf { struct capabilities { unsigned int digit_io_switch:1; unsigned int dedicated_mic:1; + unsigned int dedicated_rca:1; unsigned int output_switch:1; unsigned int mic_source_switch:1; }; diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index 60cc1d14453a..ea0a928937b6 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c @@ -1775,6 +1775,7 @@ static struct capabilities hw_capabilities(struct hw *hw) /* SB073x and Vista compatible cards have no digit IO switch */ cap.digit_io_switch = !(hw->model == CTSB073X || hw->model == CTUAA); cap.dedicated_mic = 0; + cap.dedicated_rca = 0; cap.output_switch = 0; cap.mic_source_switch = 0; diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index 5d39bc943648..214a83977a70 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c @@ -1930,6 +1930,7 @@ static struct capabilities hw_capabilities(struct hw *hw) cap.digit_io_switch = 0; cap.dedicated_mic = hw->model == CTSB1270; + cap.dedicated_rca = 0; cap.output_switch = hw->model == CTSB1270; cap.mic_source_switch = hw->model == CTSB1270; diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c index 496682613db5..fc9fde284fb3 100644 --- a/sound/pci/ctxfi/ctmixer.c +++ b/sound/pci/ctxfi/ctmixer.c @@ -547,8 +547,14 @@ static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) atc->mic_unmute(atc, state); else if (MIXER_SPDIFI_C_S == type) atc->spdif_in_unmute(atc, state); - else if (MIXER_WAVEF_P_S == type) - atc->line_front_unmute(atc, state); + else if (MIXER_WAVEF_P_S == type) { + if (cap.dedicated_rca) { + atc->rca_unmute(atc, atc->rca_state ? 0 : state); + atc->line_front_unmute(atc, atc->rca_state ? state : 0); + } else { + atc->line_front_unmute(atc, state); + } + } else if (MIXER_WAVES_P_S == type) atc->line_surround_unmute(atc, state); else if (MIXER_WAVEC_P_S == type) @@ -612,6 +618,57 @@ static struct snd_kcontrol_new swh_ctl = { .put = ct_alsa_mix_switch_put }; +static int dedicated_rca_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ + static const char *const names[2] = { + "RCA", "Front" + }; + + return snd_ctl_enum_info(info, 1, 2, names); +} + +static int dedicated_rca_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct ct_atc *atc = snd_kcontrol_chip(kcontrol); + + ucontrol->value.enumerated.item[0] = atc->rca_state; + return 0; +} + +static int dedicated_rca_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct ct_atc *atc = snd_kcontrol_chip(kcontrol); + unsigned int rca_state = ucontrol->value.enumerated.item[0]; + unsigned char state; + + if (rca_state > 1) + return -EINVAL; + + if (rca_state == atc->rca_state) + return 0; + + state = get_switch_state(atc->mixer, MIXER_WAVEF_P_S); + do_switch(atc, MIXER_WAVEF_P_S, 0); + + atc->rca_state = rca_state; + atc->dedicated_rca_select(atc); + + do_switch(atc, MIXER_WAVEF_P_S, state); + + return 1; +} + +static struct snd_kcontrol_new rca_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Analog Playback Route", + .info = dedicated_rca_info, + .get = dedicated_rca_get, + .put = dedicated_rca_put, +}; + static int ct_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -784,7 +841,17 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer) if (err) return err; } - atc->line_front_unmute(atc, 1); + + if (cap.dedicated_rca) { + err = ct_mixer_kcontrol_new(mixer, &rca_ctl); + if (err) + return err; + + atc->line_front_unmute(atc, 0); + atc->rca_unmute(atc, 1); + } else { + atc->line_front_unmute(atc, 1); + } set_switch_state(mixer, MIXER_WAVEF_P_S, 1); atc->line_surround_unmute(atc, 0); set_switch_state(mixer, MIXER_WAVES_P_S, 0); |
