diff options
Diffstat (limited to 'sound/pci/ctxfi/ctatc.c')
| -rw-r--r-- | sound/pci/ctxfi/ctatc.c | 150 | 
1 files changed, 95 insertions, 55 deletions
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 1bff80cde0a..af632bd0832 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -18,7 +18,6 @@  #include "ctatc.h"  #include "ctpcm.h"  #include "ctmixer.h" -#include "cthardware.h"  #include "ctsrc.h"  #include "ctamixer.h"  #include "ctdaio.h" @@ -30,7 +29,6 @@  #include <sound/asoundef.h>  #define MONO_SUM_SCALE	0x19a8	/* 2^(-0.5) in 14-bit floating format */ -#define DAIONUM		7  #define MAX_MULTI_CHN	8  #define IEC958_DEFAULT_CON ((IEC958_AES0_NONAUDIO \ @@ -40,7 +38,7 @@  			    | (0x10 << 16) \  			    | ((IEC958_AES3_CON_FS_48000) << 24)) -static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = { +static struct snd_pci_quirk subsys_20k1_list[] = {  	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0022, "SB055x", CTSB055X),  	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x002f, "SB055x", CTSB055X),  	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0029, "SB073x", CTSB073X), @@ -50,9 +48,11 @@ static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = {  	{ } /* terminator */  }; -static struct snd_pci_quirk __devinitdata subsys_20k2_list[] = { +static struct snd_pci_quirk subsys_20k2_list[] = {  	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB0760,  		      "SB0760", CTSB0760), +	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB1270, +		      "SB1270", CTSB1270),  	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08801,  		      "SB0880", CTSB0880),  	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08802, @@ -75,6 +75,7 @@ static const char *ct_subsys_name[NUM_CTCARDS] = {  	[CTSB0760]	= "SB076x",  	[CTHENDRIX]	= "Hendrix",  	[CTSB0880]	= "SB0880", +	[CTSB1270]      = "SB1270",  	[CT20K2_UNKNOWN] = "Unknown",  }; @@ -434,6 +435,11 @@ atc_pcm_playback_position(struct ct_atc *atc, struct ct_atc_pcm *apcm)  		return 0;  	position = src->ops->get_ca(src); +	if (position < apcm->vm_block->addr) { +		snd_printdd("ctxfi: bad ca - ca=0x%08x, vba=0x%08x, vbs=0x%08x\n", position, apcm->vm_block->addr, apcm->vm_block->size); +		position = apcm->vm_block->addr; +	} +  	size = apcm->vm_block->size;  	max_cisz = src->multi * src->rsc.msr;  	max_cisz = 128 * (max_cisz < 8 ? max_cisz : 8); @@ -459,12 +465,12 @@ static void setup_src_node_conf(struct ct_atc *atc, struct ct_atc_pcm *apcm,  				apcm->substream->runtime->rate);  	*n_srcc = 0; -	if (1 == atc->msr) { +	if (1 == atc->msr) { /* FIXME: do we really need SRC here if pitch==1 */  		*n_srcc = apcm->substream->runtime->channels;  		conf[0].pitch = pitch;  		conf[0].mix_msr = conf[0].imp_msr = conf[0].msr = 1;  		conf[0].vo = 1; -	} else if (2 == atc->msr) { +	} else if (2 <= atc->msr) {  		if (0x8000000 < pitch) {  			/* Need two-stage SRCs, SRCIMPs and  			 * AMIXERs for converting format */ @@ -869,7 +875,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)  	mutex_lock(&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); +		status &= ~(IEC958_AES3_CON_FS << 24);  		status |= (iec958_con_fs << 24);  		dao->ops->set_spos(dao, status);  		dao->ops->commit_write(dao); @@ -970,11 +976,39 @@ static int atc_select_mic_in(struct ct_atc *atc)  	return 0;  } -static int atc_have_digit_io_switch(struct ct_atc *atc) +static struct capabilities atc_capabilities(struct ct_atc *atc)  {  	struct hw *hw = atc->hw; -	return hw->have_digit_io_switch(hw); +	return hw->capabilities(hw); +} + +static int atc_output_switch_get(struct ct_atc *atc) +{ +	struct hw *hw = atc->hw; + +	return hw->output_switch_get(hw); +} + +static int atc_output_switch_put(struct ct_atc *atc, int position) +{ +	struct hw *hw = atc->hw; + +	return hw->output_switch_put(hw, position); +} + +static int atc_mic_source_switch_get(struct ct_atc *atc) +{ +	struct hw *hw = atc->hw; + +	return hw->mic_source_switch_get(hw); +} + +static int atc_mic_source_switch_put(struct ct_atc *atc, int position) +{ +	struct hw *hw = atc->hw; + +	return hw->mic_source_switch_put(hw, position);  }  static int atc_select_digit_io(struct ct_atc *atc) @@ -1045,6 +1079,11 @@ static int atc_line_in_unmute(struct ct_atc *atc, unsigned char state)  	return atc_daio_unmute(atc, state, LINEIM);  } +static int atc_mic_unmute(struct ct_atc *atc, unsigned char state) +{ +	return atc_daio_unmute(atc, state, MIC); +} +  static int atc_spdif_out_unmute(struct ct_atc *atc, unsigned char state)  {  	return atc_daio_unmute(atc, state, SPDIFOO); @@ -1215,7 +1254,7 @@ static int atc_dev_free(struct snd_device *dev)  	return ct_atc_destroy(atc);  } -static int __devinit atc_identify_card(struct ct_atc *atc, unsigned int ssid) +static int atc_identify_card(struct ct_atc *atc, unsigned int ssid)  {  	const struct snd_pci_quirk *p;  	const struct snd_pci_quirk *list; @@ -1262,7 +1301,7 @@ static int __devinit atc_identify_card(struct ct_atc *atc, unsigned int ssid)  	return 0;  } -int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc) +int ct_atc_create_alsa_devs(struct ct_atc *atc)  {  	enum CTALSADEVS i;  	int err; @@ -1285,7 +1324,7 @@ int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc)  	return 0;  } -static int __devinit atc_create_hw_devs(struct ct_atc *atc) +static int atc_create_hw_devs(struct ct_atc *atc)  {  	struct hw *hw;  	struct card_conf info = {0}; @@ -1331,17 +1370,20 @@ 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; +	int err, i, num_srcs, num_daios; + +	num_daios = ((atc->model == CTSB1270) ? 8 : 7); +	num_srcs = ((atc->model == CTSB1270) ? 6 : 4); -	atc->daios = kzalloc(sizeof(void *)*(DAIONUM), GFP_KERNEL); +	atc->daios = kzalloc(sizeof(void *)*num_daios, GFP_KERNEL);  	if (!atc->daios)  		return -ENOMEM; -	atc->srcs = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL); +	atc->srcs = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL);  	if (!atc->srcs)  		return -ENOMEM; -	atc->srcimps = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL); +	atc->srcimps = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL);  	if (!atc->srcimps)  		return -ENOMEM; @@ -1351,8 +1393,9 @@ 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, atc->n_daio = 0; i < DAIONUM-1; i++) { -		da_desc.type = i; +	for (i = 0, atc->n_daio = 0; i < num_daios; i++) { +		da_desc.type = (atc->model != CTSB073X) ? i : +			     ((i == SPDIFIO) ? SPDIFI1 : i);  		err = daio_mgr->get_daio(daio_mgr, &da_desc,  					(struct daio **)&atc->daios[i]);  		if (err) { @@ -1362,23 +1405,12 @@ static int atc_get_resources(struct ct_atc *atc)  		}  		atc->n_daio++;  	} -	if (atc->model == CTSB073X) -		da_desc.type = SPDIFI1; -	else -		da_desc.type = SPDIFIO; -	err = daio_mgr->get_daio(daio_mgr, &da_desc, -				(struct daio **)&atc->daios[i]); -	if (err) { -		printk(KERN_ERR "ctxfi: Failed to get S/PDIF-in resource!!!\n"); -		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 < (2*2); i++) { +	for (i = 0, atc->n_src = 0; i < num_srcs; i++) {  		err = src_mgr->get_src(src_mgr, &src_dsc,  					(struct src **)&atc->srcs[i]);  		if (err) @@ -1388,8 +1420,8 @@ static int atc_get_resources(struct ct_atc *atc)  	}  	srcimp_mgr = atc->rsc_mgrs[SRCIMP]; -	srcimp_dsc.msr = 8; /* SRCIMPs for S/PDIFIn SRT */ -	for (i = 0, atc->n_srcimp = 0; i < (2*1); i++) { +	srcimp_dsc.msr = 8; +	for (i = 0, atc->n_srcimp = 0; i < num_srcs; i++) {  		err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc,  					(struct srcimp **)&atc->srcimps[i]);  		if (err) @@ -1397,15 +1429,6 @@ static int atc_get_resources(struct ct_atc *atc)  		atc->n_srcimp++;  	} -	srcimp_dsc.msr = 8; /* SRCIMPs for LINE/MICIn SRT */ -	for (i = 0; i < (2*1); i++) { -		err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc, -				(struct srcimp **)&atc->srcimps[2*1+i]); -		if (err) -			return err; - -		atc->n_srcimp++; -	}  	sum_mgr = atc->rsc_mgrs[SUM];  	sum_dsc.msr = atc->msr; @@ -1488,6 +1511,18 @@ 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) { +		/* Titanium HD has a dedicated ADC for the Mic. */ +		dai = container_of(atc->daios[MIC], struct dai, daio); +		atc_connect_dai(atc->rsc_mgrs[SRC], dai, +			(struct src **)&atc->srcs[4], +			(struct srcimp **)&atc->srcimps[4]); +		src = atc->srcs[4]; +		mixer->set_input_left(mixer, MIX_MIC_IN, &src->rsc); +		src = atc->srcs[5]; +		mixer->set_input_right(mixer, MIX_MIC_IN, &src->rsc); +	} +  	dai = container_of(atc->daios[SPDIFIO], struct dai, daio);  	atc_connect_dai(atc->rsc_mgrs[SRC], dai,  			(struct src **)&atc->srcs[0], @@ -1506,8 +1541,8 @@ static void atc_connect_resources(struct ct_atc *atc)  	}  } -#ifdef CONFIG_PM -static int atc_suspend(struct ct_atc *atc, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int atc_suspend(struct ct_atc *atc)  {  	int i;  	struct hw *hw = atc->hw; @@ -1523,7 +1558,7 @@ static int atc_suspend(struct ct_atc *atc, pm_message_t state)  	atc_release_resources(atc); -	hw->suspend(hw, state); +	hw->suspend(hw);  	return 0;  } @@ -1584,7 +1619,7 @@ static int atc_resume(struct ct_atc *atc)  }  #endif -static struct ct_atc atc_preset __devinitdata = { +static struct ct_atc atc_preset = {  	.map_audio_buffer = ct_map_audio_buffer,  	.unmap_audio_buffer = ct_unmap_audio_buffer,  	.pcm_playback_prepare = atc_pcm_playback_prepare, @@ -1606,13 +1641,18 @@ static struct ct_atc atc_preset __devinitdata = {  	.line_clfe_unmute = atc_line_clfe_unmute,  	.line_rear_unmute = atc_line_rear_unmute,  	.line_in_unmute = atc_line_in_unmute, +	.mic_unmute = atc_mic_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, -	.have_digit_io_switch = atc_have_digit_io_switch, -#ifdef CONFIG_PM +	.capabilities = atc_capabilities, +	.output_switch_get = atc_output_switch_get, +	.output_switch_put = atc_output_switch_put, +	.mic_source_switch_get = atc_mic_source_switch_get, +	.mic_source_switch_put = atc_mic_source_switch_put, +#ifdef CONFIG_PM_SLEEP  	.suspend = atc_suspend,  	.resume = atc_resume,  #endif @@ -1627,13 +1667,13 @@ static struct ct_atc atc_preset __devinitdata = {   *  Creates and initializes a hardware manager.   *   *  Creates kmallocated ct_atc structure. Initializes hardware. - *  Returns 0 if suceeds, or negative error code if fails. + *  Returns 0 if succeeds, or negative error code if fails.   */ -int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci, -			    unsigned int rsr, unsigned int msr, -			    int chip_type, unsigned int ssid, -			    struct ct_atc **ratc) +int ct_atc_create(struct snd_card *card, struct pci_dev *pci, +		  unsigned int rsr, unsigned int msr, +		  int chip_type, unsigned int ssid, +		  struct ct_atc **ratc)  {  	struct ct_atc *atc;  	static struct snd_device_ops ops = { @@ -1690,15 +1730,15 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,  	atc_connect_resources(atc);  	atc->timer = ct_timer_new(atc); -	if (!atc->timer) +	if (!atc->timer) { +		err = -ENOMEM;  		goto error1; +	}  	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, atc, &ops);  	if (err < 0)  		goto error1; -	snd_card_set_dev(card, &pci->dev); -  	*ratc = atc;  	return 0;  | 
