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

📄 opti92x-ad1848.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		snd_opti93x_free(codec);		return error;	}	*rcodec = codec;	return 0;}static snd_pcm_ops_t snd_opti93x_playback_ops = {	open:		snd_opti93x_playback_open,	close:		snd_opti93x_playback_close,	ioctl:		snd_pcm_lib_ioctl,	hw_params:	snd_opti93x_hw_params,	hw_free:	snd_opti93x_hw_free,	prepare:	snd_opti93x_playback_prepare,	trigger:	snd_opti93x_playback_trigger,	pointer:	snd_opti93x_playback_pointer,};static snd_pcm_ops_t snd_opti93x_capture_ops = {	open:		snd_opti93x_capture_open,	close:		snd_opti93x_capture_close,	ioctl:		snd_pcm_lib_ioctl,	hw_params:	snd_opti93x_hw_params,	hw_free:	snd_opti93x_hw_free,	prepare:	snd_opti93x_capture_prepare,	trigger:	snd_opti93x_capture_trigger,	pointer:	snd_opti93x_capture_pointer,};static void snd_opti93x_pcm_free(snd_pcm_t *pcm){	opti93x_t *codec = snd_magic_cast(opti93x_t, pcm->private_data, return);	codec->pcm = NULL;	snd_pcm_lib_preallocate_free_for_all(pcm);}int snd_opti93x_pcm(opti93x_t *codec, int device, snd_pcm_t **rpcm){	int error;	snd_pcm_t *pcm;	if ((error = snd_pcm_new(codec->card, "OPTi 82C93X", device, 1, 1, &pcm)))		return error;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_opti93x_playback_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_opti93x_capture_ops);	pcm->private_data = codec;	pcm->private_free = snd_opti93x_pcm_free;	pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;	strcpy(pcm->name, snd_opti93x_chip_id(codec));	snd_pcm_lib_preallocate_isa_pages_for_all(pcm, 64*1024, codec->dma1 > 3 || codec->dma2 > 3 ? 128*1024 : 64*1024);	codec->pcm = pcm;	if (rpcm)		*rpcm = pcm;	return 0;}/* *  MIXER part */static int snd_opti93x_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	static char *texts[4] = {		"Line1", "Aux", "Mic", "Mix"	};	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;	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);	return 0;}static int snd_opti93x_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	opti93x_t *chip = snd_kcontrol_chip(kcontrol);	unsigned long flags;		spin_lock_irqsave(&chip->lock, flags);	ucontrol->value.enumerated.item[0] = (chip->image[OPTi93X_MIXOUT_LEFT] & OPTi93X_MIXOUT_MIXER) >> 6;	ucontrol->value.enumerated.item[1] = (chip->image[OPTi93X_MIXOUT_RIGHT] & OPTi93X_MIXOUT_MIXER) >> 6;	spin_unlock_irqrestore(&chip->lock, flags);	return 0;}static int snd_opti93x_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	opti93x_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->lock, flags);	left = (chip->image[OPTi93X_MIXOUT_LEFT] & ~OPTi93X_MIXOUT_MIXER) | left;	right = (chip->image[OPTi93X_MIXOUT_RIGHT] & ~OPTi93X_MIXOUT_MIXER) | right;	change = left != chip->image[OPTi93X_MIXOUT_LEFT] ||	         right != chip->image[OPTi93X_MIXOUT_RIGHT];	snd_opti93x_out(chip, OPTi93X_MIXOUT_LEFT, left);	snd_opti93x_out(chip, OPTi93X_MIXOUT_RIGHT, right);	spin_unlock_irqrestore(&chip->lock, flags);	return change;}#if 0#define OPTi93X_SINGLE(xname, xindex, reg, shift, mask, invert) \{ iface: SNDRV_CTL_ELEM_IFACE_MIXER, name: xname, index: xindex, \  info: snd_opti93x_info_single, \  get: snd_opti93x_get_single, put: snd_opti93x_put_single, \  private_value: reg | (shift << 8) | (mask << 16) | (invert << 24) }static int snd_opti93x_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;}static int snd_opti93x_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	opti93x_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->lock, flags);	ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;	spin_unlock_irqrestore(&chip->lock, flags);	if (invert)		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];	return 0;}static int snd_opti93x_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	opti93x_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->lock, flags);	val = (chip->image[reg] & ~(mask << shift)) | val;	change = val != chip->image[reg];	snd_opti93x_out(chip, reg, val);	spin_unlock_irqrestore(&chip->lock, flags);	return change;}#endif /* single */#define OPTi93X_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \{ iface: SNDRV_CTL_ELEM_IFACE_MIXER, name: xname, index: xindex, \  info: snd_opti93x_info_double, \  get: snd_opti93x_get_double, put: snd_opti93x_put_double, \  private_value: left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }#define OPTi93X_DOUBLE_INVERT_INVERT(xctl) \	do { xctl.private_value ^= 22; } while (0)#define OPTi93X_DOUBLE_CHANGE_REGS(xctl, left_reg, right_reg) \	do { xctl.private_value &= ~0x0000ffff; \	     xctl.private_value |= left_reg | (right_reg << 8); } while (0)static int snd_opti93x_info_double(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 = 2;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = mask;	return 0;}static int snd_opti93x_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	opti93x_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->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->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;}static int snd_opti93x_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	opti93x_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->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_opti93x_out(chip, left_reg, val1);	snd_opti93x_out(chip, right_reg, val1);	spin_unlock_irqrestore(&chip->lock, flags);	return change;}#define OPTi93X_CONTROLS (sizeof(snd_opti93x_controls)/sizeof(snd_kcontrol_new_t))static snd_kcontrol_new_t snd_opti93x_controls[] = {OPTi93X_DOUBLE("Master Playback Switch", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),OPTi93X_DOUBLE("Master Playback Volume", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 0, 0, 31, 1),OPTi93X_DOUBLE("PCM Playback Switch", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 7, 7, 1, 1),OPTi93X_DOUBLE("PCM Playback Volume", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 0, 0, 31, 0),OPTi93X_DOUBLE("FM Playback Switch", 0, OPTi931_FM_LEFT_INPUT, OPTi931_FM_RIGHT_INPUT, 7, 7, 1, 1),OPTi93X_DOUBLE("FM Playback Volume", 0, OPTi931_FM_LEFT_INPUT, OPTi931_FM_RIGHT_INPUT, 0, 0, 15, 1),OPTi93X_DOUBLE("Line Playback Switch", 0, OPTi93X_LINE_LEFT_INPUT, OPTi93X_LINE_RIGHT_INPUT, 7, 7, 1, 1),OPTi93X_DOUBLE("Line Playback Volume", 0, OPTi93X_LINE_LEFT_INPUT, OPTi93X_LINE_RIGHT_INPUT, 0, 0, 15, 1),OPTi93X_DOUBLE("Mic Playback Switch", 0, OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),OPTi93X_DOUBLE("Mic Playback Volume", 0, OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 0, 0, 15, 1),OPTi93X_DOUBLE("Mic Boost", 0, OPTi93X_MIXOUT_LEFT, OPTi93X_MIXOUT_RIGHT, 5, 5, 1, 1),OPTi93X_DOUBLE("CD Playback Switch", 0, OPTi93X_CD_LEFT_INPUT, OPTi93X_CD_RIGHT_INPUT, 7, 7, 1, 1),OPTi93X_DOUBLE("CD Playback Volume", 0, OPTi93X_CD_LEFT_INPUT, OPTi93X_CD_RIGHT_INPUT, 0, 0, 15, 1),OPTi93X_DOUBLE("Aux Playback Switch", 0, OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),OPTi93X_DOUBLE("Aux Playback Volume", 0, OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 0, 0, 15, 1),OPTi93X_DOUBLE("Capture Volume", 0, OPTi93X_MIXOUT_LEFT, OPTi93X_MIXOUT_RIGHT, 0, 0, 15, 0),{	iface: SNDRV_CTL_ELEM_IFACE_MIXER,	name: "Capture Source",	info: snd_opti93x_info_mux,	get: snd_opti93x_get_mux,	put: snd_opti93x_put_mux,}};                                        int snd_opti93x_mixer(opti93x_t *chip){	snd_card_t *card;	snd_kcontrol_new_t knew;	int err, idx;	snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);	card = chip->card;	strcpy(card->mixername, snd_opti93x_chip_id(chip));	for (idx = 0; idx < OPTi93X_CONTROLS; idx++) {		knew = snd_opti93x_controls[idx];		if (chip->hardware == OPTi9XX_HW_82C930) {			if (strstr(knew.name, "FM"))	/* skip FM controls */				continue;			else if (strcmp(knew.name, "Mic Playback Volume"))				OPTi93X_DOUBLE_INVERT_INVERT(knew);			else if (strstr(knew.name, "Aux"))				OPTi93X_DOUBLE_CHANGE_REGS(knew, OPTi930_AUX_LEFT_INPUT, OPTi930_AUX_RIGHT_INPUT);			else if (strcmp(knew.name, "PCM Playback Volume"))				OPTi93X_DOUBLE_INVERT_INVERT(knew);			else if (strcmp(knew.name, "Master Playback Volume"))				OPTi93X_DOUBLE_INVERT_INVERT(knew);		}		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_opti93x_controls[idx], chip))) < 0)			return err;	}	return 0;}#endif /* OPTi93X */static int __init snd_card_opti9xx_detect(snd_card_t *card, opti9xx_t *chip){	int i, err;	static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};#ifndef OPTi93X	for (i = OPTi9XX_HW_82C928; i < OPTi9XX_HW_82C930; i++) {		unsigned char value;		if ((err = snd_opti9xx_init(chip, i)) < 0)			return err;		chip->mc_base_size = opti9xx_mc_size[i];		if (check_region(chip->mc_base, chip->mc_base_size))			continue;		value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(1));		if ((value != 0xff) && (value != inb(chip->mc_base + 1)))			if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1)))				return 1;	}#else	/* OPTi93X */	for (i = OPTi9XX_HW_82C931; i >= OPTi9XX_HW_82C930; i--) {		unsigned long flags;		unsigned char value;		if ((err = snd_opti9xx_init(chip, i)) < 0)			return err;		chip->mc_base_size = opti9xx_mc_size[i];		if (check_region(chip->mc_base, chip->mc_base_size))			continue;		spin_lock_irqsave(&chip->lock, flags);		outb(chip->password, chip->mc_base + chip->pwd_reg);		outb(((chip->mc_indir_index & (1 << 8)) >> 4) |			((chip->mc_indir_index & 0xf0) >> 4), chip->mc_base);		spin_unlock_irqrestore(&chip->lock, flags);		value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(7));		snd_opti9xx_write(chip, OPTi9XX_MC_REG(7), 0xff - value);		if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value)			return 1;	}#endif	/* OPTi93X */	return -ENODEV;}#ifdef __ISAPNP__static int __init snd_card_opti9xx_isapnp(opti9xx_t *chip){	struct isapnp_dev *pdev = NULL;	const struct isapnp_card_id *pid = snd_card_opti9xx_pnpids-1;	static struct isapnp_card *card = NULL;      __again:	while (1) {		pid++;		if (pid->card_vendor == 0)			return -ENODEV;		if ((card = isapnp_find_card(pid->card_vendor, pid->card_device, card)))			break;	}	if (card == NULL)		return -ENODEV;	chip->dev = isapnp_find_dev(card, pid->devs[0].vendor, pid->devs[0].function, NULL);	if (chip->dev == NULL)		goto __again;	chip->devmpu = isapnp_find_dev(card, pid->devs[1].vendor, pid->devs[1].function, NULL);	pdev = chip->dev;	if (pdev->prepare(pdev) < 0)		return -EAGAIN;#ifdef OPTi93X	if (snd_port != SNDRV_AUTO_PORT)		isapnp_resource_change(&pdev->resource[0], snd_port + 4, 4);#else	if ((pid->card_device != ISAPNP_DEVICE(0x0924)) && (snd_port != SNDRV_AUTO_PORT))		isapnp_resource_change(&pdev->resource[1], snd_port, 4);#endif	/* OPTi93X */	if (snd_irq != SNDRV_AUTO_IRQ)		isapnp_resource_change(&pdev->irq_resource[0], snd_irq, 1);	if (snd_dma1 != SNDRV_AUTO_DMA)		isapnp_resource_change(&pdev->dma_resource[0], snd_dma1, 1);#if defined(CS4231) || defined(OPTi93X)	if (snd_dma2 != SNDRV_AUTO_DMA)		isapnp_resource_change(&pdev->dma_resource[1], snd_dma2, 1);#endif	/* CS4231 || OPTi93X */	if (snd_fm_port != SNDRV_AUTO_PORT)		isapnp_resource_change(&pdev->resource[1], snd_fm_port, 4);	if (pdev->activate(pdev) < 0) {		snd_printk("AUDIO isapnp configure failure\n");		return -EBUSY;	}#ifdef OPTi93X	snd_port = pdev->resource[0].start - 4;	snd_fm_port = pdev->resource[1].start;#else	if (pid->card_device != ISAPNP_DEVICE(0x0924))		snd_port = pdev->resource[1].start;	snd_fm_port = pdev->resource[2].start;#endif	/* OPTi93X */	snd_irq = pdev->irq_resource[0].start;	snd_dma1 = pdev->dma_resource[0].start;#if defined(CS4231) || defined(OPTi93X)	snd_dma2 = pdev->dma_resource[1].start;#endif	/* CS4231 || OPTi93X */	pdev = chip->devmpu;	if (pdev == NULL || pdev->prepare(pdev) < 0) {		snd_mpu_port = -1;		chip->devmpu = NULL;		return pid->card_device;	}	if (snd_mpu_port != SNDRV_AUTO_PORT)		isapnp_resource_change(&pdev->resource[0], snd_mpu_port, 2);	if (snd_mpu_irq != SNDRV_AUTO_IRQ)		isapnp_resource_change(&pdev->irq_resource[0], snd_mpu_irq, 1);	if (pdev->activate(pdev) < 0) {		snd_printk("MPU-401 isapnp configure failure\n");		snd_mpu_port = -1;		chip->devmpu = NULL;	} else {

⌨️ 快捷键说明

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