⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ymfpci_main.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	.iface = SNDRV_CTL_ELEM_IFACE_PCM,	.name = "PCM Playback Volume",	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |		SNDRV_CTL_ELEM_ACCESS_INACTIVE,	.info = snd_ymfpci_pcm_vol_info,	.get = snd_ymfpci_pcm_vol_get,	.put = snd_ymfpci_pcm_vol_put,};/* *  Mixer routines */static void snd_ymfpci_mixer_free_ac97_bus(struct snd_ac97_bus *bus){	struct snd_ymfpci *chip = bus->private_data;	chip->ac97_bus = NULL;}static void snd_ymfpci_mixer_free_ac97(struct snd_ac97 *ac97){	struct snd_ymfpci *chip = ac97->private_data;	chip->ac97 = NULL;}int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch){	struct snd_ac97_template ac97;	struct snd_kcontrol *kctl;	struct snd_pcm_substream *substream;	unsigned int idx;	int err;	static struct snd_ac97_bus_ops ops = {		.write = snd_ymfpci_codec_write,		.read = snd_ymfpci_codec_read,	};	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0)		return err;	chip->ac97_bus->private_free = snd_ymfpci_mixer_free_ac97_bus;	chip->ac97_bus->no_vra = 1; /* YMFPCI doesn't need VRA */	memset(&ac97, 0, sizeof(ac97));	ac97.private_data = chip;	ac97.private_free = snd_ymfpci_mixer_free_ac97;	if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0)		return err;	/* to be sure */	snd_ac97_update_bits(chip->ac97, AC97_EXTENDED_STATUS,			     AC97_EA_VRA|AC97_EA_VRM, 0);	for (idx = 0; idx < ARRAY_SIZE(snd_ymfpci_controls); idx++) {		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_controls[idx], chip))) < 0)			return err;	}	/* add S/PDIF control */	snd_assert(chip->pcm_spdif != NULL, return -EIO);	if ((err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_spdif_default, chip))) < 0)		return err;	kctl->id.device = chip->pcm_spdif->device;	if ((err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_spdif_mask, chip))) < 0)		return err;	kctl->id.device = chip->pcm_spdif->device;	if ((err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_spdif_stream, chip))) < 0)		return err;	kctl->id.device = chip->pcm_spdif->device;	chip->spdif_pcm_ctl = kctl;	/* direct recording source */	if (chip->device_id == PCI_DEVICE_ID_YAMAHA_754 &&	    (err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_drec_source, chip))) < 0)		return err;	/*	 * shared rear/line-in	 */	if (rear_switch) {		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_rear_shared, chip))) < 0)			return err;	}	/* per-voice volume */	substream = chip->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;	for (idx = 0; idx < 32; ++idx) {		kctl = snd_ctl_new1(&snd_ymfpci_pcm_volume, chip);		if (!kctl)			return -ENOMEM;		kctl->id.device = chip->pcm->device;		kctl->id.subdevice = idx;		kctl->private_value = (unsigned long)substream;		if ((err = snd_ctl_add(chip->card, kctl)) < 0)			return err;		chip->pcm_mixer[idx].left = 0x8000;		chip->pcm_mixer[idx].right = 0x8000;		chip->pcm_mixer[idx].ctl = kctl;		substream = substream->next;	}	return 0;}/* * timer */static int snd_ymfpci_timer_start(struct snd_timer *timer){	struct snd_ymfpci *chip;	unsigned long flags;	unsigned int count;	chip = snd_timer_chip(timer);	count = (timer->sticks << 1) - 1;	spin_lock_irqsave(&chip->reg_lock, flags);	snd_ymfpci_writew(chip, YDSXGR_TIMERCOUNT, count);	snd_ymfpci_writeb(chip, YDSXGR_TIMERCTRL, 0x03);	spin_unlock_irqrestore(&chip->reg_lock, flags);	return 0;}static int snd_ymfpci_timer_stop(struct snd_timer *timer){	struct snd_ymfpci *chip;	unsigned long flags;	chip = snd_timer_chip(timer);	spin_lock_irqsave(&chip->reg_lock, flags);	snd_ymfpci_writeb(chip, YDSXGR_TIMERCTRL, 0x00);	spin_unlock_irqrestore(&chip->reg_lock, flags);	return 0;}static int snd_ymfpci_timer_precise_resolution(struct snd_timer *timer,					       unsigned long *num, unsigned long *den){	*num = 1;	*den = 48000;	return 0;}static struct snd_timer_hardware snd_ymfpci_timer_hw = {	.flags = SNDRV_TIMER_HW_AUTO,	.resolution = 20833, /* 1/fs = 20.8333...us */	.ticks = 0x8000,	.start = snd_ymfpci_timer_start,	.stop = snd_ymfpci_timer_stop,	.precise_resolution = snd_ymfpci_timer_precise_resolution,};int __devinit snd_ymfpci_timer(struct snd_ymfpci *chip, int device){	struct snd_timer *timer = NULL;	struct snd_timer_id tid;	int err;	tid.dev_class = SNDRV_TIMER_CLASS_CARD;	tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;	tid.card = chip->card->number;	tid.device = device;	tid.subdevice = 0;	if ((err = snd_timer_new(chip->card, "YMFPCI", &tid, &timer)) >= 0) {		strcpy(timer->name, "YMFPCI timer");		timer->private_data = chip;		timer->hw = snd_ymfpci_timer_hw;	}	chip->timer = timer;	return err;}/* *  proc interface */static void snd_ymfpci_proc_read(struct snd_info_entry *entry, 				 struct snd_info_buffer *buffer){	struct snd_ymfpci *chip = entry->private_data;	int i;		snd_iprintf(buffer, "YMFPCI\n\n");	for (i = 0; i <= YDSXGR_WORKBASE; i += 4)		snd_iprintf(buffer, "%04x: %04x\n", i, snd_ymfpci_readl(chip, i));}static int __devinit snd_ymfpci_proc_init(struct snd_card *card, struct snd_ymfpci *chip){	struct snd_info_entry *entry;		if (! snd_card_proc_new(card, "ymfpci", &entry))		snd_info_set_text_ops(entry, chip, snd_ymfpci_proc_read);	return 0;}/* *  initialization routines */static void snd_ymfpci_aclink_reset(struct pci_dev * pci){	u8 cmd;	pci_read_config_byte(pci, PCIR_DSXG_CTRL, &cmd);#if 0 // force to reset	if (cmd & 0x03) {#endif		pci_write_config_byte(pci, PCIR_DSXG_CTRL, cmd & 0xfc);		pci_write_config_byte(pci, PCIR_DSXG_CTRL, cmd | 0x03);		pci_write_config_byte(pci, PCIR_DSXG_CTRL, cmd & 0xfc);		pci_write_config_word(pci, PCIR_DSXG_PWRCTRL1, 0);		pci_write_config_word(pci, PCIR_DSXG_PWRCTRL2, 0);#if 0	}#endif}static void snd_ymfpci_enable_dsp(struct snd_ymfpci *chip){	snd_ymfpci_writel(chip, YDSXGR_CONFIG, 0x00000001);}static void snd_ymfpci_disable_dsp(struct snd_ymfpci *chip){	u32 val;	int timeout = 1000;	val = snd_ymfpci_readl(chip, YDSXGR_CONFIG);	if (val)		snd_ymfpci_writel(chip, YDSXGR_CONFIG, 0x00000000);	while (timeout-- > 0) {		val = snd_ymfpci_readl(chip, YDSXGR_STATUS);		if ((val & 0x00000002) == 0)			break;	}}#ifdef CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNEL#include "ymfpci_image.h"static struct firmware snd_ymfpci_dsp_microcode = {	.size = YDSXG_DSPLENGTH,	.data = (u8 *)DspInst,};static struct firmware snd_ymfpci_controller_microcode = {	.size = YDSXG_CTRLLENGTH,	.data = (u8 *)CntrlInst,};static struct firmware snd_ymfpci_controller_1e_microcode = {	.size = YDSXG_CTRLLENGTH,	.data = (u8 *)CntrlInst1E,};#endif#ifdef CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNELstatic int snd_ymfpci_request_firmware(struct snd_ymfpci *chip){	chip->dsp_microcode = &snd_ymfpci_dsp_microcode;	if (chip->device_id == PCI_DEVICE_ID_YAMAHA_724F ||	    chip->device_id == PCI_DEVICE_ID_YAMAHA_740C ||	    chip->device_id == PCI_DEVICE_ID_YAMAHA_744 ||	    chip->device_id == PCI_DEVICE_ID_YAMAHA_754)		chip->controller_microcode =			&snd_ymfpci_controller_1e_microcode;	else		chip->controller_microcode =			&snd_ymfpci_controller_microcode;	return 0;}#else /* use fw_loader */#ifdef __LITTLE_ENDIANstatic inline void snd_ymfpci_convert_from_le(const struct firmware *fw) { }#elsestatic void snd_ymfpci_convert_from_le(const struct firmware *fw){	int i;	u32 *data = (u32 *)fw->data;	for (i = 0; i < fw->size / 4; ++i)		le32_to_cpus(&data[i]);}#endifstatic int snd_ymfpci_request_firmware(struct snd_ymfpci *chip){	int err, is_1e;	const char *name;	err = request_firmware(&chip->dsp_microcode, "yamaha/ds1_dsp.fw",			       &chip->pci->dev);	if (err >= 0) {		if (chip->dsp_microcode->size == YDSXG_DSPLENGTH)			snd_ymfpci_convert_from_le(chip->dsp_microcode);		else {			snd_printk(KERN_ERR "DSP microcode has wrong size\n");			err = -EINVAL;		}	}	if (err < 0)		return err;	is_1e = chip->device_id == PCI_DEVICE_ID_YAMAHA_724F ||		chip->device_id == PCI_DEVICE_ID_YAMAHA_740C ||		chip->device_id == PCI_DEVICE_ID_YAMAHA_744 ||		chip->device_id == PCI_DEVICE_ID_YAMAHA_754;	name = is_1e ? "yamaha/ds1e_ctrl.fw" : "yamaha/ds1_ctrl.fw";	err = request_firmware(&chip->controller_microcode, name,			       &chip->pci->dev);	if (err >= 0) {		if (chip->controller_microcode->size == YDSXG_CTRLLENGTH)			snd_ymfpci_convert_from_le(chip->controller_microcode);		else {			snd_printk(KERN_ERR "controller microcode"				   " has wrong size\n");			err = -EINVAL;		}	}	if (err < 0)		return err;	return 0;}MODULE_FIRMWARE("yamaha/ds1_dsp.fw");MODULE_FIRMWARE("yamaha/ds1_ctrl.fw");MODULE_FIRMWARE("yamaha/ds1e_ctrl.fw");#endifstatic void snd_ymfpci_download_image(struct snd_ymfpci *chip){	int i;	u16 ctrl;	u32 *inst;	snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0x00000000);	snd_ymfpci_disable_dsp(chip);	snd_ymfpci_writel(chip, YDSXGR_MODE, 0x00010000);	snd_ymfpci_writel(chip, YDSXGR_MODE, 0x00000000);	snd_ymfpci_writel(chip, YDSXGR_MAPOFREC, 0x00000000);	snd_ymfpci_writel(chip, YDSXGR_MAPOFEFFECT, 0x00000000);	snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, 0x00000000);	snd_ymfpci_writel(chip, YDSXGR_RECCTRLBASE, 0x00000000);	snd_ymfpci_writel(chip, YDSXGR_EFFCTRLBASE, 0x00000000);	ctrl = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL);	snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);	/* setup DSP instruction code */	inst = (u32 *)chip->dsp_microcode->data;	for (i = 0; i < YDSXG_DSPLENGTH / 4; i++)		snd_ymfpci_writel(chip, YDSXGR_DSPINSTRAM + (i << 2), inst[i]);	/* setup control instruction code */	inst = (u32 *)chip->controller_microcode->data;	for (i = 0; i < YDSXG_CTRLLENGTH / 4; i++)		snd_ymfpci_writel(chip, YDSXGR_CTRLINSTRAM + (i << 2), inst[i]);	snd_ymfpci_enable_dsp(chip);}static int __devinit snd_ymfpci_memalloc(struct snd_ymfpci *chip){	long size, playback_ctrl_size;	int voice, bank, reg;	u8 *ptr;	dma_addr_t ptr_addr;	playback_ctrl_size = 4 + 4 * YDSXG_PLAYBACK_VOICES;	chip->bank_size_playback = snd_ymfpci_readl(chip, YDSXGR_PLAYCTRLSIZE) << 2;	chip->bank_size_capture = snd_ymfpci_readl(chip, YDSXGR_RECCTRLSIZE) << 2;	chip->bank_size_effect = snd_ymfpci_readl(chip, YDSXGR_EFFCTRLSIZE) << 2;	chip->work_size = YDSXG_DEFAULT_WORK_SIZE;		size = ALIGN(playback_ctrl_size, 0x100) +	       ALIGN(chip->bank_size_playback * 2 * YDSXG_PLAYBACK_VOICES, 0x100) +	       ALIGN(chip->bank_size_capture * 2 * YDSXG_CAPTURE_VOICES, 0x100) +	       ALIGN(chip->bank_size_effect * 2 * YDSXG_EFFECT_VOICES, 0x100) +	       chip->work_size;	/* work_ptr must be aligned to 256 bytes, but it's already	   covered with the kernel page allocation mechanism */	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),				size, &chip->work_ptr) < 0) 		return -ENOMEM;	ptr = chip->work_ptr.area;	ptr_addr = chip->work_ptr.addr;	memset(ptr, 0, size);	/* for sure */	chip->bank_base_playback = ptr;	chip->bank_base_playback_addr = ptr_addr;	chip->ctrl_playback = (u32 *)ptr;	chip->ctrl_playback[0] = cpu_to_le32(YDSXG_PLAYBACK_VOICES);	ptr += ALIGN(playback_ctrl_size, 0x100);	ptr_addr += ALIGN(playback_ctrl_size, 0x100);	for (voice = 0; voice < YDSXG_PLAYBACK_VOICES; voice++) {		chip->voices[voice].number = voice;		chip->voices[voice].bank = (struct snd_ymfpci_playback_bank *)ptr;		chip->voices[voice].bank_addr = ptr_addr;		for (bank = 0; bank < 2; bank++) {			chip->bank_playback[voice][bank] = (struct snd_ymfpci_playback_bank *)ptr;			ptr += chip->bank_size_playback;			ptr_addr += chip->bank_size_playback;		}	}	ptr = (char *)ALIGN((unsigned long)ptr, 0x100);	ptr_addr = ALIGN(ptr_addr, 0x100);	chip->bank_base_capture = ptr;	chip->bank_base_capture_addr = ptr_addr;	for (voice = 0; voice < YDSXG_CAPTURE_VOICES; voice++)		for (bank = 0; bank < 2; bank++) {			chip->bank_capture[voice][bank] = (struct snd_ymfpci_capture_bank *)ptr;			ptr += chip->bank_size_capture;			ptr_addr += chip->bank_size_capture;		}	ptr = (char *)ALIGN((unsigned long)ptr, 0x100);	ptr_addr = ALIGN(ptr_addr, 0x100);	chip->bank_base_effect = ptr;	chip->bank_base_effect_addr = ptr_addr;	for (voice = 0; voice < YDSXG_EFFECT_VOICES; voice++)		for (bank = 0; bank < 2; bank++) {			chip->bank_effect[voice][bank] = (struct snd_ymfpci_effect_bank *)ptr;			ptr += chip->bank_size_effect;			ptr_addr += chip->bank_size_effect;		}	ptr = (char *)ALIGN((unsigned long)ptr, 0x100);	ptr_addr = ALIGN(ptr_addr, 0x100);	chip->work_base = ptr;	chip->work_base_addr = ptr_addr;		snd_assert(ptr + chip->work_size == chip->work_ptr.area + chip->work_ptr.bytes, );	snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, c

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -