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

📄 cs4231_lib.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	cs4231_t *chip;	*rchip = NULL;	chip = kzalloc(sizeof(*chip), GFP_KERNEL);	if (chip == NULL)		return -ENOMEM;	chip->hardware = hardware;	chip->hwshare = hwshare;	spin_lock_init(&chip->reg_lock);	init_MUTEX(&chip->mce_mutex);	init_MUTEX(&chip->open_mutex);	chip->card = card;	chip->rate_constraint = snd_cs4231_xrate;	chip->set_playback_format = snd_cs4231_playback_format;	chip->set_capture_format = snd_cs4231_capture_format;        memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image));                *rchip = chip;        return 0;}#ifdef LEGACY_SUPPORTint snd_cs4231_create(snd_card_t * card,	              unsigned long port,	              unsigned long cport,		      int irq, int dma1, int dma2,		      unsigned short hardware,		      unsigned short hwshare,		      cs4231_t ** rchip){	static snd_device_ops_t ops = {		.dev_free =	snd_cs4231_dev_free,	};	cs4231_t *chip;	int err;	err = snd_cs4231_new(card, hardware, hwshare, &chip);	if (err < 0)		return err;		chip->irq = -1;	chip->dma1 = -1;	chip->dma2 = -1;	if ((chip->res_port = request_region(port, 4, "CS4231")) == NULL) {		snd_printk(KERN_ERR "cs4231: can't grab port 0x%lx\n", port);		snd_cs4231_free(chip);		return -EBUSY;	}	chip->port = port;	if ((long)cport >= 0 && (chip->res_cport = request_region(cport, 8, "CS4232 Control")) == NULL) {		snd_printk(KERN_ERR "cs4231: can't grab control port 0x%lx\n", cport);		snd_cs4231_free(chip);		return -ENODEV;	}	chip->cport = cport;	if (!(hwshare & CS4231_HWSHARE_IRQ) && request_irq(irq, snd_cs4231_interrupt, SA_INTERRUPT, "CS4231", (void *) chip)) {		snd_printk(KERN_ERR "cs4231: can't grab IRQ %d\n", irq);		snd_cs4231_free(chip);		return -EBUSY;	}	chip->irq = irq;	if (!(hwshare & CS4231_HWSHARE_DMA1) && request_dma(dma1, "CS4231 - 1")) {		snd_printk(KERN_ERR "cs4231: can't grab DMA1 %d\n", dma1);		snd_cs4231_free(chip);		return -EBUSY;	}	chip->dma1 = dma1;	if (!(hwshare & CS4231_HWSHARE_DMA2) && dma1 != dma2 && dma2 >= 0 && request_dma(dma2, "CS4231 - 2")) {		snd_printk(KERN_ERR "cs4231: can't grab DMA2 %d\n", dma2);		snd_cs4231_free(chip);		return -EBUSY;	}	if (dma1 == dma2 || dma2 < 0) {		chip->single_dma = 1;		chip->dma2 = chip->dma1;	} else		chip->dma2 = dma2;	/* global setup */	if (snd_cs4231_probe(chip) < 0) {		snd_cs4231_free(chip);		return -ENODEV;	}	snd_cs4231_init(chip);	if (chip->hardware & CS4231_HW_CS4232_MASK) {		if (chip->res_cport == NULL)			snd_printk("CS4232 control port features are not accessible\n");	}	/* Register device */	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {		snd_cs4231_free(chip);		return err;	}#ifdef CONFIG_PM	/* Power Management */	chip->suspend = snd_cs4231_suspend;	chip->resume = snd_cs4231_resume;	snd_card_set_isa_pm_callback(card, snd_cs4231_pm_suspend, snd_cs4231_pm_resume, chip);#endif	*rchip = chip;	return 0;}#endif /* LEGACY_SUPPORT */static snd_pcm_ops_t snd_cs4231_playback_ops = {	.open =		snd_cs4231_playback_open,	.close =	snd_cs4231_playback_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_cs4231_playback_hw_params,	.hw_free =	snd_cs4231_playback_hw_free,	.prepare =	snd_cs4231_playback_prepare,	.trigger =	snd_cs4231_trigger,	.pointer =	snd_cs4231_playback_pointer,};static snd_pcm_ops_t snd_cs4231_capture_ops = {	.open =		snd_cs4231_capture_open,	.close =	snd_cs4231_capture_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_cs4231_capture_hw_params,	.hw_free =	snd_cs4231_capture_hw_free,	.prepare =	snd_cs4231_capture_prepare,	.trigger =	snd_cs4231_trigger,	.pointer =	snd_cs4231_capture_pointer,};static void snd_cs4231_pcm_free(snd_pcm_t *pcm){	cs4231_t *chip = pcm->private_data;	chip->pcm = NULL;	snd_pcm_lib_preallocate_free_for_all(pcm);}int snd_cs4231_pcm(cs4231_t *chip, int device, snd_pcm_t **rpcm){	snd_pcm_t *pcm;	int err;	if ((err = snd_pcm_new(chip->card, "CS4231", device, 1, 1, &pcm)) < 0)		return err;	spin_lock_init(&chip->reg_lock);	init_MUTEX(&chip->mce_mutex);	init_MUTEX(&chip->open_mutex);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs4231_playback_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs4231_capture_ops);		/* global setup */	pcm->private_data = chip;	pcm->private_free = snd_cs4231_pcm_free;	pcm->info_flags = 0;	if (chip->single_dma)		pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;	if (chip->hardware != CS4231_HW_INTERWAVE)		pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;	strcpy(pcm->name, snd_cs4231_chip_id(chip));#ifdef LEGACY_SUPPORT	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_isa_data(),					      64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);#else#  ifdef EBUS_SUPPORT        if (chip->ebus_flag) {                snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,                				      chip->dev_u.pdev,						      64*1024, 128*1024);        } else {#  endif#  ifdef SBUS_SUPPORT                snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS,                				      chip->dev_u.sdev,						      64*1024, 128*1024);#  endif#  ifdef EBUS_SUPPORT        }#  endif#endif	chip->pcm = pcm;	if (rpcm)		*rpcm = pcm;	return 0;}static void snd_cs4231_timer_free(snd_timer_t *timer){	cs4231_t *chip = timer->private_data;	chip->timer = NULL;}int snd_cs4231_timer(cs4231_t *chip, int device, snd_timer_t **rtimer){	snd_timer_t *timer;	snd_timer_id_t tid;	int err;	/* Timer initialization */	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, "CS4231", &tid, &timer)) < 0)		return err;	strcpy(timer->name, snd_cs4231_chip_id(chip));	timer->private_data = chip;	timer->private_free = snd_cs4231_timer_free;	timer->hw = snd_cs4231_timer_table;	chip->timer = timer;	if (rtimer)		*rtimer = timer;	return 0;}	/* *  MIXER part */static int snd_cs4231_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	static char *texts[4] = {		"Line", "Aux", "Mic", "Mix"	};	static char *opl3sa_texts[4] = {		"Line", "CD", "Mic", "Mix"	};	static char *gusmax_texts[4] = {		"Line", "Synth", "Mic", "Mix"	};	char **ptexts = texts;	cs4231_t *chip = snd_kcontrol_chip(kcontrol);	snd_assert(chip->card != NULL, return -EINVAL);	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;	uinfo->count = 2;	uinfo->value.enumerated.items = 4;	if (uinfo->value.enumerated.item > 3)		uinfo->value.enumerated.item = 3;	if (!strcmp(chip->card->driver, "GUS MAX"))		ptexts = gusmax_texts;	switch (chip->hardware) {	case CS4231_HW_INTERWAVE: ptexts = gusmax_texts; break;	case CS4231_HW_OPL3SA2: ptexts = opl3sa_texts; break;	}	strcpy(uinfo->value.enumerated.name, ptexts[uinfo->value.enumerated.item]);	return 0;}static int snd_cs4231_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	cs4231_t *chip = snd_kcontrol_chip(kcontrol);	unsigned long flags;		spin_lock_irqsave(&chip->reg_lock, flags);	ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6;	ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6;	spin_unlock_irqrestore(&chip->reg_lock, flags);	return 0;}static int snd_cs4231_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	cs4231_t *chip = snd_kcontrol_chip(kcontrol);	unsigned long flags;	unsigned short left, right;	int change;		if (ucontrol->value.enumerated.item[0] > 3 ||	    ucontrol->value.enumerated.item[1] > 3)		return -EINVAL;	left = ucontrol->value.enumerated.item[0] << 6;	right = ucontrol->value.enumerated.item[1] << 6;	spin_lock_irqsave(&chip->reg_lock, flags);	left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left;	right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right;	change = left != chip->image[CS4231_LEFT_INPUT] ||	         right != chip->image[CS4231_RIGHT_INPUT];	snd_cs4231_out(chip, CS4231_LEFT_INPUT, left);	snd_cs4231_out(chip, CS4231_RIGHT_INPUT, right);	spin_unlock_irqrestore(&chip->reg_lock, flags);	return change;}int snd_cs4231_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	int mask = (kcontrol->private_value >> 16) & 0xff;	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 1;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = mask;	return 0;}int snd_cs4231_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	cs4231_t *chip = snd_kcontrol_chip(kcontrol);	unsigned long flags;	int reg = kcontrol->private_value & 0xff;	int shift = (kcontrol->private_value >> 8) & 0xff;	int mask = (kcontrol->private_value >> 16) & 0xff;	int invert = (kcontrol->private_value >> 24) & 0xff;		spin_lock_irqsave(&chip->reg_lock, flags);	ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;	spin_unlock_irqrestore(&chip->reg_lock, flags);	if (invert)		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];	return 0;}int snd_cs4231_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	cs4231_t *chip = snd_kcontrol_chip(kcontrol);	unsigned long flags;	int reg = kcontrol->private_value & 0xff;	int shift = (kcontrol->private_value >> 8) & 0xff;	int mask = (kcontrol->private_value >> 16) & 0xff;	int invert = (kcontrol->private_value >> 24) & 0xff;	int change;	unsigned short val;		val = (ucontrol->value.integer.value[0] & mask);	if (invert)		val = mask - val;	val <<= shift;	spin_lock_irqsave(&chip->reg_lock, flags);	val = (chip->image[reg] & ~(mask << shift)) | val;	change = val != chip->image[reg];	snd_cs4231_out(chip, reg, val);	spin_unlock_irqrestore(&chip->reg_lock, flags);	return change;}int snd_cs4231_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	int mask = (kcontrol->private_value >> 24) & 0xff;	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 2;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = mask;	return 0;}int snd_cs4231_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	cs4231_t *chip = snd_kcontrol_chip(kcontrol);	unsigned long flags;	int left_reg = kcontrol->private_value & 0xff;	int right_reg = (kcontrol->private_value >> 8) & 0xff;	int shift_left = (kcontrol->private_value >> 16) & 0x07;	int shift_right = (kcontrol->private_value >> 19) & 0x07;	int mask = (kcontrol->private_value >> 24) & 0xff;	int invert = (kcontrol->private_value >> 22) & 1;		spin_lock_irqsave(&chip->reg_lock, flags);	ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;	ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;	spin_unlock_irqrestore(&chip->reg_lock, flags);	if (invert) {		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];		ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];	}	return 0;}int snd_cs4231_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	cs4231_t *chip = snd_kcontrol_chip(kcontrol);	unsigned long flags;	int left_reg = kcontrol->private_value & 0xff;	int right_reg = (kcontrol->private_value >> 8) & 0xff;	int shift_left = (kcontrol->private_value >> 16) & 0x07;	int shift_right = (kcontrol->private_value >> 19) & 0x07;	int mask = (kcontrol->private_value >> 24) & 0xff;	int invert = (kcontrol->private_value >> 22) & 1;	int change;	unsigned short val1, val2;		val1 = ucontrol->value.integer.value[0] & mask;	val2 = ucontrol->value.integer.value[1] & mask;	if (invert) {		val1 = mask - val1;		val2 = mask - val2;	}	val1 <<= shift_left;	val2 <<= shift_right;	spin_lock_irqsave(&chip->reg_lock, flags);	val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;	val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;	change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg];	snd_cs4231_out(chip, left_reg, val1);	snd_cs4231_out(chip, right_reg, val2);	spin_unlock_irqrestore(&chip->reg_lock, flags);	return change;}static snd_kcontrol_new_t snd_cs4231_controls[] = {CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),CS4231_SINGLE("Mono Playback Switch", 0, CS4231_MONO_CTRL, 7, 1, 1),CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),CS4231_SINGLE("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, 6, 1, 1),CS4231_SINGLE("Mono Output Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0),CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	.name = "Capture Source",	.info = snd_cs4231_info_mux,	.get = snd_cs4231_get_mux,	.put = snd_cs4231_put_mux,},CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0),CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1)};                                        int snd_cs4231_mixer(cs4231_t *chip){	snd_card_t *card;	unsigned int idx;	int err;	snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL);	card = chip->card;	strcpy(card->mixername, chip->pcm->name);	for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) {		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4231_controls[idx], chip))) < 0)			return err;	}	return 0;}EXPORT_SYMBOL(snd_cs4231_out);EXPORT_SYMBOL(snd_cs4231_in);EXPORT_SYMBOL(snd_cs4236_ext_out);EXPORT_SYMBOL(snd_cs4236_ext_in);EXPORT_SYMBOL(snd_cs4231_mce_up);EXPORT_SYMBOL(snd_cs4231_mce_down);EXPORT_SYMBOL(snd_cs4231_interrupt);EXPORT_SYMBOL(snd_cs4231_chip_id);EXPORT_SYMBOL(snd_cs4231_create);EXPORT_SYMBOL(snd_cs4231_pcm);EXPORT_SYMBOL(snd_cs4231_mixer);EXPORT_SYMBOL(snd_cs4231_timer);EXPORT_SYMBOL(snd_cs4231_info_single);EXPORT_SYMBOL(snd_cs4231_get_single);EXPORT_SYMBOL(snd_cs4231_put_single);EXPORT_SYMBOL(snd_cs4231_info_double);EXPORT_SYMBOL(snd_cs4231_get_double);EXPORT_SYMBOL(snd_cs4231_put_double);/* *  INIT part */static int __init alsa_cs4231_init(void){	return 0;}static void __exit alsa_cs4231_exit(void){}module_init(alsa_cs4231_init)module_exit(alsa_cs4231_exit)

⌨️ 快捷键说明

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