Пример #1
0
static int __devinit snd_vortex_mixer(vortex_t * vortex)
{
	struct snd_ac97_bus *pbus;
	struct snd_ac97_template ac97;
	int err;
	static struct snd_ac97_bus_ops ops = {
		.write = vortex_codec_write,
		.read = vortex_codec_read,
	};

	if ((err = snd_ac97_bus(vortex->card, 0, &ops, NULL, &pbus)) < 0)
		return err;
	memset(&ac97, 0, sizeof(ac97));
	// Intialize AC97 codec stuff.
	ac97.private_data = vortex;
	ac97.scaps = AC97_SCAP_NO_SPDIF;
	err = snd_ac97_mixer(pbus, &ac97, &vortex->codec);
	vortex->isquad = ((vortex->codec == NULL) ?  0 : (vortex->codec->ext_id&0x80));
	return err;
}
Пример #2
0
static int snd_als300_ac97(struct snd_als300 *chip)
{
	struct snd_ac97_bus *bus;
	struct snd_ac97_template ac97;
	int err;
	static struct snd_ac97_bus_ops ops = {
		.write = snd_als300_ac97_write,
		.read = snd_als300_ac97_read,
	};

	snd_als300_dbgcallenter();
	if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus)) < 0)
		return err;

	memset(&ac97, 0, sizeof(ac97));
	ac97.private_data = chip;

	snd_als300_dbgcallleave();
	return snd_ac97_mixer(bus, &ac97, &chip->ac97);
}
Пример #3
0
/* create an ac97 mixer interface */
static int __devinit
snd_nm256_mixer(nm256_t *chip)
{
	ac97_bus_t *pbus;
	ac97_template_t ac97;
	int i, err;
	static ac97_bus_ops_t ops = {
		.reset = snd_nm256_ac97_reset,
		.write = snd_nm256_ac97_write,
		.read = snd_nm256_ac97_read,
	};
	/* looks like nm256 hangs up when unexpected registers are touched... */
	static int mixer_regs[] = {
		AC97_MASTER, AC97_HEADPHONE, AC97_MASTER_MONO,
		AC97_PC_BEEP, AC97_PHONE, AC97_MIC, AC97_LINE, AC97_CD,
		AC97_VIDEO, AC97_AUX, AC97_PCM, AC97_REC_SEL,
		AC97_REC_GAIN, AC97_GENERAL_PURPOSE, AC97_3D_CONTROL,
		/*AC97_EXTENDED_ID,*/
		AC97_VENDOR_ID1, AC97_VENDOR_ID2,
		-1
	};

	if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
		return err;

	memset(&ac97, 0, sizeof(ac97));
	ac97.scaps = AC97_SCAP_AUDIO; /* we support audio! */
	ac97.limited_regs = 1;
	for (i = 0; mixer_regs[i] >= 0; i++)
		set_bit(mixer_regs[i], ac97.reg_accessed);
	ac97.private_data = chip;
	pbus->no_vra = 1;
	err = snd_ac97_mixer(pbus, &ac97, &chip->ac97);
	if (err < 0)
		return err;
	if (! (chip->ac97->id & (0xf0000000))) {
		/* looks like an invalid id */
		sprintf(chip->card->mixername, "%s AC97", chip->card->driver);
	}
	return 0;
}
Пример #4
0
static int ac97_soc_probe(struct snd_soc_codec *codec)
{
	struct snd_ac97 *ac97;
	struct snd_ac97_bus *ac97_bus;
	struct snd_ac97_template ac97_template;
	int ret;

	/* add codec as bus device for standard ac97 */
	ret = snd_ac97_bus(codec->component.card->snd_card, 0, soc_ac97_ops,
			   NULL, &ac97_bus);
	if (ret < 0)
		return ret;

	memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);
	if (ret < 0)
		return ret;

	snd_soc_codec_set_drvdata(codec, ac97);

	return 0;
}
Пример #5
0
static int ac97_soc_probe(struct snd_soc_codec *codec)
{
	struct snd_ac97_bus *ac97_bus;
	struct snd_ac97_template ac97_template;
	int ret;

	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
	if (ret < 0) {
		printk(KERN_ERR "ASoC: failed to init generic ac97 glue\n");
		return ret;
	}

	/* add codec as bus device for standard ac97 */
	ret = snd_ac97_bus(codec->card->snd_card, 0, &soc_ac97_ops, NULL, &ac97_bus);
	if (ret < 0)
		return ret;

	memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
	if (ret < 0)
		return ret;

	return 0;
}
static int snd_atiixp_pcm_open(struct snd_pcm_substream *substream,
			       struct atiixp_dma *dma, int pcm_type)
{
	struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
	struct snd_pcm_runtime *runtime = substream->runtime;
	int err;
	static unsigned int rates[] = { 8000,  9600, 12000, 16000 };
	static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
		.count = ARRAY_SIZE(rates),
		.list = rates,
		.mask = 0,
	};

	if (snd_BUG_ON(!dma->ops || !dma->ops->enable_dma))
		return -EINVAL;

	if (dma->opened)
		return -EBUSY;
	dma->substream = substream;
	runtime->hw = snd_atiixp_pcm_hw;
	dma->ac97_pcm_type = pcm_type;
	if ((err = snd_pcm_hw_constraint_list(runtime, 0,
					      SNDRV_PCM_HW_PARAM_RATE,
					      &hw_constraints_rates)) < 0)
		return err;
	if ((err = snd_pcm_hw_constraint_integer(runtime,
						 SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
		return err;
	runtime->private_data = dma;

	/*                 */
	spin_lock_irq(&chip->reg_lock);
	dma->ops->enable_dma(chip, 1);
	spin_unlock_irq(&chip->reg_lock);
	dma->opened = 1;

	return 0;
}

static int snd_atiixp_pcm_close(struct snd_pcm_substream *substream,
				struct atiixp_dma *dma)
{
	struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
	/*                  */
	if (snd_BUG_ON(!dma->ops || !dma->ops->enable_dma))
		return -EINVAL;
	spin_lock_irq(&chip->reg_lock);
	dma->ops->enable_dma(chip, 0);
	spin_unlock_irq(&chip->reg_lock);
	dma->substream = NULL;
	dma->opened = 0;
	return 0;
}

/*
 */
static int snd_atiixp_playback_open(struct snd_pcm_substream *substream)
{
	struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
	int err;

	mutex_lock(&chip->open_mutex);
	err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 0);
	mutex_unlock(&chip->open_mutex);
	if (err < 0)
		return err;
	return 0;
}

static int snd_atiixp_playback_close(struct snd_pcm_substream *substream)
{
	struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
	int err;
	mutex_lock(&chip->open_mutex);
	err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]);
	mutex_unlock(&chip->open_mutex);
	return err;
}

static int snd_atiixp_capture_open(struct snd_pcm_substream *substream)
{
	struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
	return snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_CAPTURE], 1);
}

static int snd_atiixp_capture_close(struct snd_pcm_substream *substream)
{
	struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
	return snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_CAPTURE]);
}


/*               */
static struct snd_pcm_ops snd_atiixp_playback_ops = {
	.open =		snd_atiixp_playback_open,
	.close =	snd_atiixp_playback_close,
	.ioctl =	snd_pcm_lib_ioctl,
	.hw_params =	snd_atiixp_pcm_hw_params,
	.hw_free =	snd_atiixp_pcm_hw_free,
	.prepare =	snd_atiixp_playback_prepare,
	.trigger =	snd_atiixp_pcm_trigger,
	.pointer =	snd_atiixp_pcm_pointer,
};

/*              */
static struct snd_pcm_ops snd_atiixp_capture_ops = {
	.open =		snd_atiixp_capture_open,
	.close =	snd_atiixp_capture_close,
	.ioctl =	snd_pcm_lib_ioctl,
	.hw_params =	snd_atiixp_pcm_hw_params,
	.hw_free =	snd_atiixp_pcm_hw_free,
	.prepare =	snd_atiixp_capture_prepare,
	.trigger =	snd_atiixp_pcm_trigger,
	.pointer =	snd_atiixp_pcm_pointer,
};

static struct atiixp_dma_ops snd_atiixp_playback_dma_ops = {
	.type = ATI_DMA_PLAYBACK,
	.llp_offset = ATI_REG_MODEM_OUT_DMA1_LINKPTR,
	.dt_cur = ATI_REG_MODEM_OUT_DMA1_DT_CUR,
	.enable_dma = atiixp_out_enable_dma,
	.enable_transfer = atiixp_out_enable_transfer,
	.flush_dma = atiixp_out_flush_dma,
};
	
static struct atiixp_dma_ops snd_atiixp_capture_dma_ops = {
	.type = ATI_DMA_CAPTURE,
	.llp_offset = ATI_REG_MODEM_IN_DMA_LINKPTR,
	.dt_cur = ATI_REG_MODEM_IN_DMA_DT_CUR,
	.enable_dma = atiixp_in_enable_dma,
	.enable_transfer = atiixp_in_enable_transfer,
	.flush_dma = atiixp_in_flush_dma,
};

static int __devinit snd_atiixp_pcm_new(struct atiixp_modem *chip)
{
	struct snd_pcm *pcm;
	int err;

	/*                      */
	chip->dmas[ATI_DMA_PLAYBACK].ops = &snd_atiixp_playback_dma_ops;
	chip->dmas[ATI_DMA_CAPTURE].ops = &snd_atiixp_capture_dma_ops;

	/*                    */
	err = snd_pcm_new(chip->card, "ATI IXP MC97", ATI_PCMDEV_ANALOG, 1, 1, &pcm);
	if (err < 0)
		return err;
	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_atiixp_playback_ops);
	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_atiixp_capture_ops);
	pcm->dev_class = SNDRV_PCM_CLASS_MODEM;
	pcm->private_data = chip;
	strcpy(pcm->name, "ATI IXP MC97");
	chip->pcmdevs[ATI_PCMDEV_ANALOG] = pcm;

	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
					      snd_dma_pci_data(chip->pci),
					      64*1024, 128*1024);

	return 0;
}



/*
                    
 */
static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id)
{
	struct atiixp_modem *chip = dev_id;
	unsigned int status;

	status = atiixp_read(chip, ISR);

	if (! status)
		return IRQ_NONE;

	/*                   */
	if (status & ATI_REG_ISR_MODEM_OUT1_XRUN)
		snd_atiixp_xrun_dma(chip,  &chip->dmas[ATI_DMA_PLAYBACK]);
	else if (status & ATI_REG_ISR_MODEM_OUT1_STATUS)
		snd_atiixp_update_dma(chip, &chip->dmas[ATI_DMA_PLAYBACK]);
	if (status & ATI_REG_ISR_MODEM_IN_XRUN)
		snd_atiixp_xrun_dma(chip,  &chip->dmas[ATI_DMA_CAPTURE]);
	else if (status & ATI_REG_ISR_MODEM_IN_STATUS)
		snd_atiixp_update_dma(chip, &chip->dmas[ATI_DMA_CAPTURE]);

	/*                     */
	if (status & CODEC_CHECK_BITS) {
		unsigned int detected;
		detected = status & CODEC_CHECK_BITS;
		spin_lock(&chip->reg_lock);
		chip->codec_not_ready_bits |= detected;
		atiixp_update(chip, IER, detected, 0); /*                           */
		spin_unlock(&chip->reg_lock);
	}

	/*     */
	atiixp_write(chip, ISR, status);

	return IRQ_HANDLED;
}


/*
                     
 */

static int __devinit snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock)
{
	struct snd_ac97_bus *pbus;
	struct snd_ac97_template ac97;
	int i, err;
	int codec_count;
	static struct snd_ac97_bus_ops ops = {
		.write = snd_atiixp_ac97_write,
		.read = snd_atiixp_ac97_read,
	};
	static unsigned int codec_skip[NUM_ATI_CODECS] = {
		ATI_REG_ISR_CODEC0_NOT_READY,
		ATI_REG_ISR_CODEC1_NOT_READY,
		ATI_REG_ISR_CODEC2_NOT_READY,
	};

	if (snd_atiixp_codec_detect(chip) < 0)
		return -ENXIO;

	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0)
		return err;
	pbus->clock = clock;
	chip->ac97_bus = pbus;

	codec_count = 0;
	for (i = 0; i < NUM_ATI_CODECS; i++) {
		if (chip->codec_not_ready_bits & codec_skip[i])
			continue;
		memset(&ac97, 0, sizeof(ac97));
		ac97.private_data = chip;
		ac97.pci = chip->pci;
		ac97.num = i;
		ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE;
		if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
			chip->ac97[i] = NULL; /*            */
			snd_printdd("atiixp-modem: codec %d not available for modem\n", i);
			continue;
		}
		codec_count++;
	}

	if (! codec_count) {
		snd_printk(KERN_ERR "atiixp-modem: no codec available\n");
		return -ENODEV;
	}

	/*                                                  */

	return 0;
}


#ifdef CONFIG_PM
/*
                   
 */
static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state)
{
	struct snd_card *card = pci_get_drvdata(pci);
	struct atiixp_modem *chip = card->private_data;
	int i;

	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
	for (i = 0; i < NUM_ATI_PCMDEVS; i++)
		snd_pcm_suspend_all(chip->pcmdevs[i]);
	for (i = 0; i < NUM_ATI_CODECS; i++)
		snd_ac97_suspend(chip->ac97[i]);
	snd_atiixp_aclink_down(chip);
	snd_atiixp_chip_stop(chip);

	pci_disable_device(pci);
	pci_save_state(pci);
	pci_set_power_state(pci, pci_choose_state(pci, state));
	return 0;
}

static int snd_atiixp_resume(struct pci_dev *pci)
{
	struct snd_card *card = pci_get_drvdata(pci);
	struct atiixp_modem *chip = card->private_data;
	int i;

	pci_set_power_state(pci, PCI_D0);
	pci_restore_state(pci);
	if (pci_enable_device(pci) < 0) {
		printk(KERN_ERR "atiixp-modem: pci_enable_device failed, "
		       "disabling device\n");
		snd_card_disconnect(card);
		return -EIO;
	}
	pci_set_master(pci);

	snd_atiixp_aclink_reset(chip);
	snd_atiixp_chip_start(chip);

	for (i = 0; i < NUM_ATI_CODECS; i++)
		snd_ac97_resume(chip->ac97[i]);

	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
	return 0;
}
#endif /*           */


#ifdef CONFIG_PROC_FS
/*
                                   
 */

static void snd_atiixp_proc_read(struct snd_info_entry *entry,
				 struct snd_info_buffer *buffer)
{
	struct atiixp_modem *chip = entry->private_data;
	int i;

	for (i = 0; i < 256; i += 4)
		snd_iprintf(buffer, "%02x: %08x\n", i, readl(chip->remap_addr + i));
}

static void __devinit snd_atiixp_proc_init(struct atiixp_modem *chip)
{
	struct snd_info_entry *entry;

	if (! snd_card_proc_new(chip->card, "atiixp-modem", &entry))
		snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read);
}
#else
#define snd_atiixp_proc_init(chip)
#endif


/*
             
 */

static int snd_atiixp_free(struct atiixp_modem *chip)
{
	if (chip->irq < 0)
		goto __hw_end;
	snd_atiixp_chip_stop(chip);

      __hw_end:
	if (chip->irq >= 0)
		free_irq(chip->irq, chip);
	if (chip->remap_addr)
		iounmap(chip->remap_addr);
	pci_release_regions(chip->pci);
	pci_disable_device(chip->pci);
	kfree(chip);
	return 0;
}

static int snd_atiixp_dev_free(struct snd_device *device)
{
	struct atiixp_modem *chip = device->device_data;
	return snd_atiixp_free(chip);
}

/*
                                
 */
static int __devinit snd_atiixp_create(struct snd_card *card,
				       struct pci_dev *pci,
				       struct atiixp_modem **r_chip)
{
	static struct snd_device_ops ops = {
		.dev_free =	snd_atiixp_dev_free,
	};
	struct atiixp_modem *chip;
	int err;

	if ((err = pci_enable_device(pci)) < 0)
		return err;

	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
	if (chip == NULL) {
		pci_disable_device(pci);
		return -ENOMEM;
	}

	spin_lock_init(&chip->reg_lock);
	mutex_init(&chip->open_mutex);
	chip->card = card;
	chip->pci = pci;
	chip->irq = -1;
	if ((err = pci_request_regions(pci, "ATI IXP MC97")) < 0) {
		kfree(chip);
		pci_disable_device(pci);
		return err;
	}
	chip->addr = pci_resource_start(pci, 0);
	chip->remap_addr = pci_ioremap_bar(pci, 0);
	if (chip->remap_addr == NULL) {
		snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
		snd_atiixp_free(chip);
		return -EIO;
	}

	if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED,
			KBUILD_MODNAME, chip)) {
		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
		snd_atiixp_free(chip);
		return -EBUSY;
	}
	chip->irq = pci->irq;
	pci_set_master(pci);
	synchronize_irq(chip->irq);

	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
		snd_atiixp_free(chip);
		return err;
	}

	snd_card_set_dev(card, &pci->dev);

	*r_chip = chip;
	return 0;
}


static int __devinit snd_atiixp_probe(struct pci_dev *pci,
				      const struct pci_device_id *pci_id)
{
	struct snd_card *card;
	struct atiixp_modem *chip;
	int err;

	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
	if (err < 0)
		return err;

	strcpy(card->driver, "ATIIXP-MODEM");
	strcpy(card->shortname, "ATI IXP Modem");
	if ((err = snd_atiixp_create(card, pci, &chip)) < 0)
		goto __error;
	card->private_data = chip;

	if ((err = snd_atiixp_aclink_reset(chip)) < 0)
		goto __error;

	if ((err = snd_atiixp_mixer_new(chip, ac97_clock)) < 0)
		goto __error;

	if ((err = snd_atiixp_pcm_new(chip)) < 0)
		goto __error;
	
	snd_atiixp_proc_init(chip);

	snd_atiixp_chip_start(chip);

	sprintf(card->longname, "%s rev %x at 0x%lx, irq %i",
		card->shortname, pci->revision, chip->addr, chip->irq);

	if ((err = snd_card_register(card)) < 0)
		goto __error;

	pci_set_drvdata(pci, card);
	return 0;

 __error:
	snd_card_free(card);
	return err;
}

static void __devexit snd_atiixp_remove(struct pci_dev *pci)
{
	snd_card_free(pci_get_drvdata(pci));
	pci_set_drvdata(pci, NULL);
}
Пример #7
0
int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
				int pcm_device, int multi_device)
{
	int err, pcm;
	struct snd_kcontrol *kctl;
	struct snd_card *card = emu->card;
	char **c;
	static char *emu10k1_remove_ctls[] = {
		/* no AC97 mono, surround, center/lfe */
		"Master Mono Playback Switch",
		"Master Mono Playback Volume",
		"PCM Out Path & Mute",
		"Mono Output Select",
		"Front Playback Switch",
		"Front Playback Volume",
		"Surround Playback Switch",
		"Surround Playback Volume",
		"Center Playback Switch",
		"Center Playback Volume",
		"LFE Playback Switch",
		"LFE Playback Volume",
		NULL
	};
	static char *emu10k1_rename_ctls[] = {
		"Surround Digital Playback Volume", "Surround Playback Volume",
		"Center Digital Playback Volume", "Center Playback Volume",
		"LFE Digital Playback Volume", "LFE Playback Volume",
		NULL
	};
	static char *audigy_remove_ctls[] = {
		/* Master/PCM controls on ac97 of Audigy has no effect */
		/* On the Audigy2 the AC97 playback is piped into
		 * the Philips ADC for 24bit capture */
		"PCM Playback Switch",
		"PCM Playback Volume",
		"Master Mono Playback Switch",
		"Master Mono Playback Volume",
		"Master Playback Switch",
		"Master Playback Volume",
		"PCM Out Path & Mute",
		"Mono Output Select",
		/* remove unused AC97 capture controls */
		"Capture Source",
		"Capture Switch",
		"Capture Volume",
		"Mic Select",
		"Video Playback Switch",
		"Video Playback Volume",
		"Mic Playback Switch",
		"Mic Playback Volume",
		NULL
	};
	static char *audigy_rename_ctls[] = {
		/* use conventional names */
		"Wave Playback Volume", "PCM Playback Volume",
		/* "Wave Capture Volume", "PCM Capture Volume", */
		"Wave Master Playback Volume", "Master Playback Volume",
		"AMic Playback Volume", "Mic Playback Volume",
		NULL
	};
	static char *audigy_remove_ctls_1361t_adc[] = {
		/* On the Audigy2 the AC97 playback is piped into
		 * the Philips ADC for 24bit capture */
		"PCM Playback Switch",
		"PCM Playback Volume",
		"Master Mono Playback Switch",
		"Master Mono Playback Volume",
		"Capture Source",
		"Capture Switch",
		"Capture Volume",
		"Mic Capture Volume",
		"Headphone Playback Switch",
		"Headphone Playback Volume",
		"3D Control - Center",
		"3D Control - Depth",
		"3D Control - Switch",
		"Line2 Playback Volume",
		"Line2 Capture Volume",
		NULL
	};
	static char *audigy_rename_ctls_1361t_adc[] = {
		"Master Playback Switch", "Master Capture Switch",
		"Master Playback Volume", "Master Capture Volume",
		"Wave Master Playback Volume", "Master Playback Volume",
		"PC Speaker Playback Switch", "PC Speaker Capture Switch",
		"PC Speaker Playback Volume", "PC Speaker Capture Volume",
		"Phone Playback Switch", "Phone Capture Switch",
		"Phone Playback Volume", "Phone Capture Volume",
		"Mic Playback Switch", "Mic Capture Switch",
		"Mic Playback Volume", "Mic Capture Volume",
		"Line Playback Switch", "Line Capture Switch",
		"Line Playback Volume", "Line Capture Volume",
		"CD Playback Switch", "CD Capture Switch",
		"CD Playback Volume", "CD Capture Volume",
		"Aux Playback Switch", "Aux Capture Switch",
		"Aux Playback Volume", "Aux Capture Volume",
		"Video Playback Switch", "Video Capture Switch",
		"Video Playback Volume", "Video Capture Volume",

		NULL
	};

	if (emu->card_capabilities->ac97_chip) {
		struct snd_ac97_bus *pbus;
		struct snd_ac97_template ac97;
		static struct snd_ac97_bus_ops ops = {
			.write = snd_emu10k1_ac97_write,
			.read = snd_emu10k1_ac97_read,
		};

		if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
			return err;
		pbus->no_vra = 1; /* we don't need VRA */
		
		memset(&ac97, 0, sizeof(ac97));
		ac97.private_data = emu;
		ac97.private_free = snd_emu10k1_mixer_free_ac97;
		ac97.scaps = AC97_SCAP_NO_SPDIF;
		if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) {
			if (emu->card_capabilities->ac97_chip == 1)
				return err;
			snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n");
			snd_printd(KERN_INFO"          Proceeding without ac97 mixers...\n");
			snd_device_free(emu->card, pbus);
			goto no_ac97; /* FIXME: get rid of ugly gotos.. */
		}
		if (emu->audigy) {
			/* set master volume to 0 dB */
			snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
			/* set capture source to mic */
			snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
			if (emu->card_capabilities->adc_1361t)
				c = audigy_remove_ctls_1361t_adc;
			else 
				c = audigy_remove_ctls;
		} else {
			/*
			 * Credits for cards based on STAC9758:
			 *   James Courtier-Dutton <*****@*****.**>
			 *   Voluspa <*****@*****.**>
			 */
			if (emu->ac97->id == AC97_ID_STAC9758) {
				emu->rear_ac97 = 1;
				snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT);
			}
			/* remove unused AC97 controls */
			snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
			snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
			c = emu10k1_remove_ctls;
		}
		for (; *c; c++)
			remove_ctl(card, *c);
	} else {
Пример #8
0
int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
{
	ac97_t ac97;
	int err, pcm, idx;
	snd_kcontrol_t *kctl;
	snd_card_t *card = emu->card;

	if (!emu->APS) {
		memset(&ac97, 0, sizeof(ac97));
		ac97.write = snd_emu10k1_ac97_write;
		ac97.read = snd_emu10k1_ac97_read;
		ac97.private_data = emu;
		ac97.private_free = snd_emu10k1_mixer_free_ac97;
		if ((err = snd_ac97_mixer(emu->card, &ac97, &emu->ac97)) < 0)
			return err;
	} else {
		strcpy(emu->card->mixername, "EMU APS");
	}

	for (pcm = 0; pcm < 32; pcm++) {
		emu10k1_pcm_mixer_t *mix;
		int v;
		
		mix = &emu->pcm_mixer[pcm];
		mix->epcm = NULL;

		if ((kctl = mix->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
			return -ENOMEM;
		kctl->private_value = (long)mix;
		kctl->id.index = pcm;
		if ((err = snd_ctl_add(card, kctl)))
			return err;
		for (v = 0; v < 4; v++)
			mix->send_routing[0][v] = 
				mix->send_routing[1][v] = 
				mix->send_routing[2][v] = v;
		
		if ((kctl = mix->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
			return -ENOMEM;
		kctl->private_value = (long)mix;
		kctl->id.index = pcm;
		if ((err = snd_ctl_add(card, kctl)))
			return err;
		memset(&mix->send_volume, 0, sizeof(mix->send_volume));
		mix->send_volume[0][0] = mix->send_volume[0][1] =
		mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
		
		if ((kctl = mix->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
			return -ENOMEM;
		kctl->private_value = (long)mix;
		kctl->id.index = pcm;
		if ((err = snd_ctl_add(card, kctl)))
			return err;
		mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
	}
	
	for (idx = 0; idx < 3; idx++) {
		if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
			return -ENOMEM;
		kctl->private_value = idx;
		kctl->id.index = idx;
		if ((err = snd_ctl_add(card, kctl)))
			return err;
		if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
			return -ENOMEM;
		kctl->private_value = idx;
		kctl->id.index = idx;
		if ((err = snd_ctl_add(card, kctl)))
			return err;
	}

	if (emu->audigy) {
#if 0 // XXX
		if ((kctl = snd_ctl_new1(&audigy_output_analog, emu)) == NULL)
			return -ENOMEM;
		if ((err = snd_ctl_add(card, kctl)))
			return err;
		if ((kctl = snd_ctl_new1(&audigy_output_digital, emu)) == NULL)
			return -ENOMEM;
		if ((err = snd_ctl_add(card, kctl)))
			return err;
#endif // XXX
	} else {
		if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
			return -ENOMEM;
		if ((err = snd_ctl_add(card, kctl)))
			return err;
	}

	return 0;
}
Пример #9
0
static int pxa2xx_ac97_probe(struct device *dev)
{
	snd_card_t *card;
	ac97_bus_t *ac97_bus;
	ac97_template_t ac97_template;
	int ret;
	struct platform_device *pdev = to_platform_device(dev);

	ret = -ENOMEM;
	card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
			    THIS_MODULE, 0);
	if (!card)
		goto err;

	card->dev = dev;
	strncpy(card->driver, dev->driver->name, sizeof(card->driver));

	ret = pxa2xx_pcm_new(card, &pxa2xx_ac97_pcm_client, &pxa2xx_ac97_pcm);
	if (ret)
		goto err;

	ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL);
	if (ret < 0)
		goto err;

	pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
	pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
	pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
	pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
#ifdef CONFIG_PXA27x
	/* Use GPIO 113 as AC97 Reset on Bulverde */
	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
#endif
	pxa_set_cken(CKEN2_AC97, 1);

	ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus);
	if (ret)
		goto err;
	memset(&ac97_template, 0, sizeof(ac97_template));
	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &pxa2xx_ac97_ac97);
	if (ret)
		goto err;

	snprintf(card->shortname, sizeof(card->shortname),
		 "%s", snd_ac97_get_short_name(pxa2xx_ac97_ac97));
	snprintf(card->longname, sizeof(card->longname),
		 "%s (%s)", dev->driver->name, card->mixername);

	snd_card_set_pm_callback(card, pxa2xx_ac97_do_suspend,
				 pxa2xx_ac97_do_resume, NULL);
	ret = snd_card_register(card);
#if defined(CONFIG_MACH_MAINSTONE) && defined(CONFIG_DPM)
	pdev->dev.constraints = &pxa_ac97_constraints;
	assert_constraints(pdev->dev.constraints);
#endif /* CONFIG_MACH_MAINSTONE && CONFIG_DPM */
	if (ret == 0) {
		dev_set_drvdata(dev, card);
		return 0;
	}

 err:
	if (card)
		snd_card_free(card);
	if (CKEN & CKEN2_AC97) {
		GCR |= GCR_ACLINK_OFF;
		free_irq(IRQ_AC97, NULL);
		pxa_set_cken(CKEN2_AC97, 0);
	}
	return ret;
}
Пример #10
0
static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
{
	struct snd_card *card;
	struct snd_ac97_bus *ac97_bus;
	struct snd_ac97_template ac97_template;
	int ret;

	ret = -ENOMEM;
	card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
			    THIS_MODULE, 0);
	if (!card)
		goto err;

	card->dev = &dev->dev;
	strncpy(card->driver, dev->dev.driver->name, sizeof(card->driver));

	ret = pxa2xx_pcm_new(card, &pxa2xx_ac97_pcm_client, &pxa2xx_ac97_pcm);
	if (ret)
		goto err;

	ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL);
	if (ret < 0)
		goto err;

	pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
	pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
	pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
	pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
#ifdef CONFIG_PXA27x
	/* Use GPIO 113 as AC97 Reset on Bulverde */
	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
#endif
	pxa_set_cken(CKEN_AC97, 1);

	ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus);
	if (ret)
		goto err;
	memset(&ac97_template, 0, sizeof(ac97_template));
	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &pxa2xx_ac97_ac97);
	if (ret)
		goto err;

	snprintf(card->shortname, sizeof(card->shortname),
		 "%s", snd_ac97_get_short_name(pxa2xx_ac97_ac97));
	snprintf(card->longname, sizeof(card->longname),
		 "%s (%s)", dev->dev.driver->name, card->mixername);

	snd_card_set_dev(card, &dev->dev);
	ret = snd_card_register(card);
	if (ret == 0) {
		platform_set_drvdata(dev, card);
		return 0;
	}

 err:
	if (card)
		snd_card_free(card);
	if (CKEN & (1 << CKEN_AC97)) {
		GCR |= GCR_ACLINK_OFF;
		free_irq(IRQ_AC97, NULL);
		pxa_set_cken(CKEN_AC97, 0);
	}
	return ret;
}