diff options
Diffstat (limited to 'sound/pci/ctxfi/ctatc.c')
| -rw-r--r-- | sound/pci/ctxfi/ctatc.c | 125 |
1 files changed, 84 insertions, 41 deletions
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 2a3e9d8ba7db..227d8c8490e1 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -25,6 +25,9 @@ #include <sound/control.h> #include <sound/asoundef.h> +#define NUM_ATC_SRCS 6 +#define NUM_ATC_PCM (2 * 4) + #define MONO_SUM_SCALE 0x19a8 /* 2^(-0.5) in 14-bit floating format */ #define MAX_MULTI_CHN 8 @@ -60,6 +63,7 @@ static const struct snd_pci_quirk subsys_20k2_list[] = { SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_CREATIVE, 0xf000, PCI_SUBDEVICE_ID_CREATIVE_HENDRIX, "HENDRIX", CTHENDRIX), + SND_PCI_QUIRK(0x160b, 0x0101, "OK0010", CTOK0010), { } /* terminator */ }; @@ -75,6 +79,7 @@ static const char *ct_subsys_name[NUM_CTCARDS] = { [CTHENDRIX] = "Hendrix", [CTSB0880] = "SB0880", [CTSB1270] = "SB1270", + [CTOK0010] = "OK0010", [CT20K2_UNKNOWN] = "Unknown", }; @@ -295,10 +300,10 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) src = apcm->src; for (i = 0; i < n_amixer; i++) { amixer = apcm->amixers[i]; - mutex_lock(&atc->atc_mutex); - amixer->ops->setup(amixer, &src->rsc, - INIT_VOL, atc->pcm[i+device*2]); - mutex_unlock(&atc->atc_mutex); + scoped_guard(mutex, &atc->atc_mutex) { + amixer->ops->setup(amixer, &src->rsc, + INIT_VOL, atc->pcm[i+device*2]); + } src = src->ops->next_interleave(src); if (!src) src = apcm->src; @@ -874,7 +879,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) return -ENOENT; } - mutex_lock(&atc->atc_mutex); + guard(mutex)(&atc->atc_mutex); dao->ops->get_spos(dao, &status); if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) { status &= ~(IEC958_AES3_CON_FS << 24); @@ -884,7 +889,6 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) } if ((rate != atc->pll_rate) && (32000 != rate)) err = atc_pll_init(atc, rate); - mutex_unlock(&atc->atc_mutex); return err; } @@ -921,13 +925,13 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) src = apcm->src; } /* Connect to SPDIFOO */ - mutex_lock(&atc->atc_mutex); - dao = container_of(atc->daios[SPDIFOO], struct dao, daio); - amixer = apcm->amixers[0]; - dao->ops->set_left_input(dao, &amixer->rsc); - amixer = apcm->amixers[1]; - dao->ops->set_right_input(dao, &amixer->rsc); - mutex_unlock(&atc->atc_mutex); + scoped_guard(mutex, &atc->atc_mutex) { + dao = container_of(atc->daios[SPDIFOO], struct dao, daio); + amixer = apcm->amixers[0]; + dao->ops->set_left_input(dao, &amixer->rsc); + amixer = apcm->amixers[1]; + dao->ops->set_right_input(dao, &amixer->rsc); + } ct_timer_prepare(apcm->timer); @@ -985,6 +989,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; @@ -1086,6 +1108,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); @@ -1115,7 +1142,7 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state) struct rsc *rscs[2] = {NULL}; unsigned int spos = 0; - mutex_lock(&atc->atc_mutex); + guard(mutex)(&atc->atc_mutex); dao = container_of(atc->daios[SPDIFOO], struct dao, daio); da_dsc.msr = state ? 1 : atc->msr; da_dsc.passthru = state ? 1 : 0; @@ -1133,7 +1160,6 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state) } dao->ops->set_spos(dao, spos); dao->ops->commit_write(dao); - mutex_unlock(&atc->atc_mutex); return err; } @@ -1163,9 +1189,11 @@ static int atc_release_resources(struct ct_atc *atc) if (atc->daios) { daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO]; - for (i = 0; i < atc->n_daio; i++) { + for (i = 0; i < NUM_DAIOTYP; i++) { daio = atc->daios[i]; - if (daio->type < LINEIM) { + if (!daio) + continue; + if (daio->output) { dao = container_of(daio, struct dao, daio); dao->ops->clear_left_input(dao); dao->ops->clear_right_input(dao); @@ -1178,8 +1206,9 @@ static int atc_release_resources(struct ct_atc *atc) if (atc->pcm) { sum_mgr = atc->rsc_mgrs[SUM]; - for (i = 0; i < atc->n_pcm; i++) - sum_mgr->put_sum(sum_mgr, atc->pcm[i]); + for (i = 0; i < NUM_ATC_PCM; i++) + if (atc->pcm[i]) + sum_mgr->put_sum(sum_mgr, atc->pcm[i]); kfree(atc->pcm); atc->pcm = NULL; @@ -1187,8 +1216,9 @@ static int atc_release_resources(struct ct_atc *atc) if (atc->srcs) { src_mgr = atc->rsc_mgrs[SRC]; - for (i = 0; i < atc->n_src; i++) - src_mgr->put_src(src_mgr, atc->srcs[i]); + for (i = 0; i < NUM_ATC_SRCS; i++) + if (atc->srcs[i]) + src_mgr->put_src(src_mgr, atc->srcs[i]); kfree(atc->srcs); atc->srcs = NULL; @@ -1196,7 +1226,9 @@ static int atc_release_resources(struct ct_atc *atc) if (atc->srcimps) { srcimp_mgr = atc->rsc_mgrs[SRCIMP]; - for (i = 0; i < atc->n_srcimp; i++) { + for (i = 0; i < NUM_ATC_SRCS; i++) { + if (!atc->srcimps[i]) + continue; srcimp = atc->srcimps[i]; srcimp->ops->unmap(srcimp); srcimp_mgr->put_srcimp(srcimp_mgr, atc->srcimps[i]); @@ -1296,6 +1328,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; } @@ -1369,32 +1402,35 @@ static int atc_get_resources(struct ct_atc *atc) struct srcimp_mgr *srcimp_mgr; struct sum_desc sum_dsc = {0}; struct sum_mgr *sum_mgr; - int err, i, num_srcs, num_daios; + struct capabilities cap; + int err, i; - num_daios = ((atc->model == CTSB1270) ? 8 : 7); - num_srcs = ((atc->model == CTSB1270) ? 6 : 4); + cap = atc->capabilities(atc); - atc->daios = kcalloc(num_daios, sizeof(void *), GFP_KERNEL); + atc->daios = kcalloc(NUM_DAIOTYP, sizeof(void *), GFP_KERNEL); if (!atc->daios) return -ENOMEM; - atc->srcs = kcalloc(num_srcs, sizeof(void *), GFP_KERNEL); + atc->srcs = kcalloc(NUM_ATC_SRCS, sizeof(void *), GFP_KERNEL); if (!atc->srcs) return -ENOMEM; - atc->srcimps = kcalloc(num_srcs, sizeof(void *), GFP_KERNEL); + atc->srcimps = kcalloc(NUM_ATC_SRCS, sizeof(void *), GFP_KERNEL); if (!atc->srcimps) return -ENOMEM; - atc->pcm = kcalloc(2 * 4, sizeof(void *), GFP_KERNEL); + atc->pcm = kcalloc(NUM_ATC_PCM, sizeof(void *), GFP_KERNEL); if (!atc->pcm) return -ENOMEM; daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO]; da_desc.msr = atc->msr; - for (i = 0, atc->n_daio = 0; i < num_daios; i++) { + for (i = 0; i < NUM_DAIOTYP; i++) { + 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) || (i == RCA); err = daio_mgr->get_daio(daio_mgr, &da_desc, (struct daio **)&atc->daios[i]); if (err) { @@ -1403,42 +1439,39 @@ static int atc_get_resources(struct ct_atc *atc) i); return err; } - atc->n_daio++; } src_mgr = atc->rsc_mgrs[SRC]; src_dsc.multi = 1; src_dsc.msr = atc->msr; src_dsc.mode = ARCRW; - for (i = 0, atc->n_src = 0; i < num_srcs; i++) { + for (i = 0; i < NUM_ATC_SRCS; i++) { + if (((i > 3) && !cap.dedicated_mic)) + continue; err = src_mgr->get_src(src_mgr, &src_dsc, (struct src **)&atc->srcs[i]); if (err) return err; - - atc->n_src++; } srcimp_mgr = atc->rsc_mgrs[SRCIMP]; srcimp_dsc.msr = 8; - for (i = 0, atc->n_srcimp = 0; i < num_srcs; i++) { + for (i = 0; i < NUM_ATC_SRCS; i++) { + if (((i > 3) && !cap.dedicated_mic)) + continue; err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc, (struct srcimp **)&atc->srcimps[i]); if (err) return err; - - atc->n_srcimp++; } sum_mgr = atc->rsc_mgrs[SUM]; sum_dsc.msr = atc->msr; - for (i = 0, atc->n_pcm = 0; i < (2*4); i++) { + for (i = 0; i < NUM_ATC_PCM; i++) { err = sum_mgr->get_sum(sum_mgr, &sum_dsc, (struct sum **)&atc->pcm[i]); if (err) return err; - - atc->n_pcm++; } return 0; @@ -1491,9 +1524,11 @@ static void atc_connect_resources(struct ct_atc *atc) struct sum *sum; struct ct_mixer *mixer; struct rsc *rscs[2] = {NULL}; + struct capabilities cap; int i, j; mixer = atc->mixer; + cap = atc->capabilities(atc); for (i = MIX_WAVE_FRONT, j = LINEO1; i <= MIX_SPDIF_OUT; i++, j++) { mixer->get_output_ports(mixer, i, &rscs[0], &rscs[1]); @@ -1502,6 +1537,11 @@ static void atc_connect_resources(struct ct_atc *atc) dao->ops->set_right_input(dao, rscs[1]); } + if (cap.dedicated_rca) { + /* SE-300PCIE has a dedicated DAC for the 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], @@ -1511,8 +1551,9 @@ static void atc_connect_resources(struct ct_atc *atc) src = atc->srcs[3]; mixer->set_input_right(mixer, MIX_LINE_IN, &src->rsc); - if (atc->model == CTSB1270) { + if (cap.dedicated_mic) { /* Titanium HD has a dedicated ADC for the Mic. */ + /* SE-300PCIE has a 4-channel ADC. */ dai = container_of(atc->daios[MIC], struct dai, daio); atc_connect_dai(atc->rsc_mgrs[SRC], dai, (struct src **)&atc->srcs[4], @@ -1634,12 +1675,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, |
