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

📄 opti92x-ad1848.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	.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 = pcm->private_data;	codec->pcm = NULL;	snd_pcm_lib_preallocate_free_for_all(pcm);}static 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_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_isa_data(),					      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_image(chip, OPTi93X_MIXOUT_LEFT, left);	snd_opti93x_out_image(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 >> 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;}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_image(chip, left_reg, val1);	snd_opti93x_out_image(chip, right_reg, val2);	spin_unlock_irqrestore(&chip->lock, flags);	return change;}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, 1, 1, 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, 1),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, 1, 1, 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, 1, 1, 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, 1, 1, 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, 1, 1, 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, 1, 1, 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,}};                                        static int snd_opti93x_mixer(opti93x_t *chip){	snd_card_t *card;	snd_kcontrol_new_t knew;	int err;	unsigned int 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 < ARRAY_SIZE(snd_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 __devinit snd_card_opti9xx_detect(snd_card_t *card, opti9xx_t *chip){	int i, err;#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;		if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL)			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;		release_and_free_resource(chip->res_mc_base);		chip->res_mc_base = NULL;	}#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;		if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL)			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;		release_and_free_resource(chip->res_mc_base);		chip->res_mc_base = NULL;	}#endif	/* OPTi93X */	return -ENODEV;}#ifdef CONFIG_PNPstatic int __devinit snd_card_opti9xx_pnp(opti9xx_t *chip, struct pnp_card_link *card,					  const struct pnp_card_device_id *pid){	struct pnp_dev *pdev;	struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);	int err;	chip->dev = pnp_request_card_device(card, pid->devs[0].id, NULL);	if (chip->dev == NULL) {		kfree(cfg);		return -EBUSY;	}	chip->devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);	pdev = chip->dev;	pnp_init_resource_table(cfg);#ifdef OPTi93X	if (port != SNDRV_AUTO_PORT)		pnp_resource_change(&cfg->port_resource[0], port + 4, 4);#else	if (pid->driver_data != 0x0924 && port != SNDRV_AUTO_PORT)		pnp_resource_change(&cfg->port_resource[1], port, 4);#endif	/* OPTi93X */	if (irq != SNDRV_AUTO_IRQ)		pnp_resource_change(&cfg->irq_resource[0], irq, 1);	if (dma1 != SNDRV_AUTO_DMA)		pnp_resource_change(&cfg->dma_resource[0], dma1, 1);#if defined(CS4231) || defined(OPTi93X)	if (dma2 != SNDRV_AUTO_DMA)		pnp_resource_change(&cfg->dma_resource[1], dma2, 1);#else#ifdef snd_opti9xx_fixup_dma2	snd_opti9xx_fixup_dma2(pdev);#endif#endif	/* CS4231 || OPTi93X */#ifdef OPTi93X	if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT)		pnp_resource_change(&cfg->port_resource[1], fm_port, 4);#else	if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT)		pnp_resource_change(&cfg->port_resource[2], fm_port, 4);#endif	if (pnp_manual_config_dev(pdev, cfg, 0) < 0)		snd_printk(KERN_ERR "AUDIO the requested resources are invalid, using auto config\n");	err = pnp_activate_dev(pdev);	if (err < 0) {		snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err);		kfree(cfg);		return err;	}#ifdef OPTi93X	port = pnp_port_start(pdev, 0) - 4;	fm_port = pnp_port_start(pdev, 1);#else	if (pid->driver_data != 0x0924)		port = pnp_port_start(pdev, 1);	fm_port = pnp_port_start(pdev, 2);#endif	/* OPTi93X */	irq = pnp_irq(pdev, 0);	dma1 = pnp_dma(pdev, 0);#if defined(CS4231) || defined(OPTi93X)	dma2 = pnp_dma(pdev, 1);#endif	/* CS4231 || OPTi93X */	pdev = chip->devmpu;	if (pdev && mpu_port > 0) {		pnp_init_resource_table(cfg);		if (mpu_port != SNDRV_AUTO_PORT)			pnp_resource_change(&cfg->port_resource[0], mpu_port, 2);		if (mpu_irq != SNDRV_AUTO_IRQ)			pnp_resource_change(&cfg->irq_resource[0], mpu_irq, 1);		if (pnp_manual_config_dev(pdev, cfg, 0) < 0)			snd_printk(KERN_ERR "AUDIO the requested resources are invalid, using auto config\n");		err = pnp_activate_dev(pdev);		if (err < 0) {			snd_printk(KERN_ERR "AUDIO pnp configure failure\n");			mpu_port = -1;			chip->devmpu = NULL;		} else {			mpu_port = pnp_port_start(pdev, 0);			mpu_irq = pnp_irq(pdev, 0);		}	}	kfree(cfg);

⌨️ 快捷键说明

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