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

📄 opti92x-ad1848.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (!(chip->mode & OPTi93X_MODE_OPEN)) {		outb(0x00, OPTi93X_PORT(chip, STATUS));		snd_opti93x_out_mask(chip, OPTi93X_PIN_CTRL,			OPTi93X_IRQ_ENABLE, OPTi93X_IRQ_ENABLE);		chip->mode = mode;	}	else		chip->mode |= mode;	spin_unlock_irqrestore(&chip->lock, flags);	return 0;}static void snd_opti93x_close(opti93x_t *chip, unsigned int mode){	unsigned long flags;	spin_lock_irqsave(&chip->lock, flags);	chip->mode &= ~mode;	if (chip->mode & OPTi93X_MODE_OPEN) {		spin_unlock_irqrestore(&chip->lock, flags);		return;	}	snd_opti93x_mute(chip, 1);	outb(0, OPTi93X_PORT(chip, STATUS));	snd_opti93x_out_mask(chip, OPTi93X_PIN_CTRL, OPTi93X_IRQ_ENABLE,		~OPTi93X_IRQ_ENABLE);	snd_opti93x_mce_up(chip);	snd_opti93x_out_image(chip, OPTi93X_IFACE_CONF, 0x00);	snd_opti93x_mce_down(chip);	chip->mode = 0;	snd_opti93x_mute(chip, 0);	spin_unlock_irqrestore(&chip->lock, flags);}static int snd_opti93x_trigger(snd_pcm_substream_t *substream, 			       unsigned char what, int cmd){	opti93x_t *chip = snd_pcm_substream_chip(substream);	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:	case SNDRV_PCM_TRIGGER_STOP:	{		unsigned int what = 0;		struct list_head *pos;		snd_pcm_substream_t *s;		snd_pcm_group_for_each(pos, substream) {			s = snd_pcm_group_substream_entry(pos);			if (s == chip->playback_substream) {				what |= OPTi93X_PLAYBACK_ENABLE;				snd_pcm_trigger_done(s, substream);			} else if (s == chip->capture_substream) {				what |= OPTi93X_CAPTURE_ENABLE;				snd_pcm_trigger_done(s, substream);			}		}		spin_lock(&chip->lock);		if (cmd == SNDRV_PCM_TRIGGER_START) {			snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF, what, what);			if (what & OPTi93X_CAPTURE_ENABLE)				udelay(50);		} else			snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF, what, 0x00);		spin_unlock(&chip->lock);		break;	}	default:		return -EINVAL;	}	return 0;}static int snd_opti93x_playback_trigger(snd_pcm_substream_t *substream, int cmd){	return snd_opti93x_trigger(substream,				   OPTi93X_PLAYBACK_ENABLE, cmd);}static int snd_opti93x_capture_trigger(snd_pcm_substream_t * substream, int cmd){	return snd_opti93x_trigger(substream,				   OPTi93X_CAPTURE_ENABLE, cmd);}static int snd_opti93x_hw_params(snd_pcm_substream_t * substream,				 snd_pcm_hw_params_t * hw_params){	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));}static int snd_opti93x_hw_free(snd_pcm_substream_t * substream){	snd_pcm_lib_free_pages(substream);	return 0;}static int snd_opti93x_playback_prepare(snd_pcm_substream_t * substream){	opti93x_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	unsigned long flags;	unsigned char format;	unsigned int count = snd_pcm_lib_period_bytes(substream);	unsigned int size = snd_pcm_lib_buffer_bytes(substream);	spin_lock_irqsave(&chip->lock, flags);	chip->p_dma_size = size;	snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF,		OPTi93X_PLAYBACK_ENABLE | OPTi93X_PLAYBACK_PIO,		~(OPTi93X_PLAYBACK_ENABLE | OPTi93X_PLAYBACK_PIO));	snd_dma_program(chip->dma1, runtime->dma_addr, size,		DMA_MODE_WRITE | DMA_AUTOINIT);	format = snd_opti93x_get_freq(runtime->rate);	format |= snd_opti93x_get_format(chip, runtime->format,		runtime->channels);	snd_opti93x_playback_format(chip, format);	format = chip->image[OPTi93X_PLAY_FORMAT];	count = snd_opti93x_get_count(format, count) - 1;	snd_opti93x_out_image(chip, OPTi93X_PLAY_LWR_CNT, count);	snd_opti93x_out_image(chip, OPTi93X_PLAY_UPR_CNT, count >> 8);	spin_unlock_irqrestore(&chip->lock, flags);	return 0;}static int snd_opti93x_capture_prepare(snd_pcm_substream_t *substream){	opti93x_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	unsigned long flags;	unsigned char format;	unsigned int count = snd_pcm_lib_period_bytes(substream);	unsigned int size = snd_pcm_lib_buffer_bytes(substream);	spin_lock_irqsave(&chip->lock, flags);	chip->c_dma_size = size;	snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF,		OPTi93X_CAPTURE_ENABLE | OPTi93X_CAPTURE_PIO, 0);	snd_dma_program(chip->dma2, runtime->dma_addr, size,		DMA_MODE_READ | DMA_AUTOINIT);	format = snd_opti93x_get_freq(runtime->rate);	format |= snd_opti93x_get_format(chip, runtime->format,		runtime->channels);	snd_opti93x_capture_format(chip, format);	format = chip->image[OPTi93X_CAPT_FORMAT];	count = snd_opti93x_get_count(format, count) - 1;	snd_opti93x_out_image(chip, OPTi93X_CAPT_LWR_CNT, count);	snd_opti93x_out_image(chip, OPTi93X_CAPT_UPR_CNT, count >> 8);	spin_unlock_irqrestore(&chip->lock, flags);	return 0;}static snd_pcm_uframes_t snd_opti93x_playback_pointer(snd_pcm_substream_t *substream){	opti93x_t *chip = snd_pcm_substream_chip(substream);	size_t ptr;	if (!(chip->image[OPTi93X_IFACE_CONF] & OPTi93X_PLAYBACK_ENABLE))		return 0;	ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size);	return bytes_to_frames(substream->runtime, ptr);}static snd_pcm_uframes_t snd_opti93x_capture_pointer(snd_pcm_substream_t *substream){	opti93x_t *chip = snd_pcm_substream_chip(substream);	size_t ptr;		if (!(chip->image[OPTi93X_IFACE_CONF] & OPTi93X_CAPTURE_ENABLE))		return 0;	ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);	return bytes_to_frames(substream->runtime, ptr);}static void snd_opti93x_overrange(opti93x_t *chip){	unsigned long flags;	spin_lock_irqsave(&chip->lock, flags);	if (snd_opti93x_in(chip, OPTi93X_ERR_INIT) & (0x08 | 0x02))		chip->capture_substream->runtime->overrange++;	spin_unlock_irqrestore(&chip->lock, flags);}static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id, struct pt_regs *regs){	opti93x_t *codec = dev_id;	unsigned char status;	status = snd_opti9xx_read(codec->chip, OPTi9XX_MC_REG(11));	if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream)		snd_pcm_period_elapsed(codec->playback_substream);	if ((status & OPTi93X_IRQ_CAPTURE) && codec->capture_substream) {		snd_opti93x_overrange(codec);		snd_pcm_period_elapsed(codec->capture_substream);	}	outb(0x00, OPTi93X_PORT(codec, STATUS));	return IRQ_HANDLED;}static snd_pcm_hardware_t snd_opti93x_playback = {	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),	.formats =		(SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |				 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),	.rates =		SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,	.rate_min =		5512,	.rate_max =		48000,	.channels_min =		1,	.channels_max =		2,	.buffer_bytes_max =	(128*1024),	.period_bytes_min =	64,	.period_bytes_max =	(128*1024),	.periods_min =		1,	.periods_max =		1024,	.fifo_size =		0,};static snd_pcm_hardware_t snd_opti93x_capture = {	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),	.formats =		(SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |				 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),	.rates =		SNDRV_PCM_RATE_8000_48000,	.rate_min =		5512,	.rate_max =		48000,	.channels_min =		1,	.channels_max =		2,	.buffer_bytes_max =	(128*1024),	.period_bytes_min =	64,	.period_bytes_max =	(128*1024),	.periods_min =		1,	.periods_max =		1024,	.fifo_size =		0,};static int snd_opti93x_playback_open(snd_pcm_substream_t *substream){	int error;	opti93x_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	if ((error = snd_opti93x_open(chip, OPTi93X_MODE_PLAY)) < 0)		return error;	snd_pcm_set_sync(substream);	chip->playback_substream = substream;	runtime->hw = snd_opti93x_playback;	snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);	return error;}static int snd_opti93x_capture_open(snd_pcm_substream_t *substream){	int error;	opti93x_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	if ((error = snd_opti93x_open(chip, OPTi93X_MODE_CAPTURE)) < 0)		return error;	runtime->hw = snd_opti93x_capture;	snd_pcm_set_sync(substream);	chip->capture_substream = substream;	snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);	return error;}static int snd_opti93x_playback_close(snd_pcm_substream_t *substream){	opti93x_t *chip = snd_pcm_substream_chip(substream);	chip->playback_substream = NULL;	snd_opti93x_close(chip, OPTi93X_MODE_PLAY);	return 0;}static int snd_opti93x_capture_close(snd_pcm_substream_t *substream){	opti93x_t *chip = snd_pcm_substream_chip(substream);	chip->capture_substream = NULL;	snd_opti93x_close(chip, OPTi93X_MODE_CAPTURE);	return 0;}static void snd_opti93x_init(opti93x_t *chip){	unsigned long flags;	int i;	spin_lock_irqsave(&chip->lock, flags);	snd_opti93x_mce_up(chip);	for (i = 0; i < 32; i++)		snd_opti93x_out_image(chip, i, snd_opti93x_default_image[i]);	snd_opti93x_mce_down(chip);	spin_unlock_irqrestore(&chip->lock, flags);}static int snd_opti93x_probe(opti93x_t *chip){	unsigned long flags;	unsigned char val;	spin_lock_irqsave(&chip->lock, flags);	val = snd_opti93x_in(chip, OPTi93X_ID) & 0x0f;	spin_unlock_irqrestore(&chip->lock, flags);	return (val == 0x0a) ? 0 : -ENODEV;}static int snd_opti93x_free(opti93x_t *chip){	release_and_free_resource(chip->res_port);	if (chip->dma1 >= 0) {		disable_dma(chip->dma1);		free_dma(chip->dma1);	}	if (chip->dma2 >= 0) {		disable_dma(chip->dma2);		free_dma(chip->dma2);	}	if (chip->irq >= 0) {	  free_irq(chip->irq, chip);	}	kfree(chip);	return 0;}static int snd_opti93x_dev_free(snd_device_t *device){	opti93x_t *chip = device->device_data;	return snd_opti93x_free(chip);}static const char *snd_opti93x_chip_id(opti93x_t *codec){	switch (codec->hardware) {	case OPTi9XX_HW_82C930: return "82C930";	case OPTi9XX_HW_82C931: return "82C931";	case OPTi9XX_HW_82C933: return "82C933";	default:		return "???";	}}static int snd_opti93x_create(snd_card_t *card, opti9xx_t *chip,			      int dma1, int dma2,			      opti93x_t **rcodec){	static snd_device_ops_t ops = {		.dev_free =	snd_opti93x_dev_free,	};	int error;	opti93x_t *codec;	*rcodec = NULL;	codec = kzalloc(sizeof(*codec), GFP_KERNEL);	if (codec == NULL)		return -ENOMEM;	codec->irq = -1;	codec->dma1 = -1;	codec->dma2 = -1;	if ((codec->res_port = request_region(chip->wss_base + 4, 4, "OPTI93x CODEC")) == NULL) {		snd_printk(KERN_ERR "opti9xx: can't grab port 0x%lx\n", chip->wss_base + 4);		snd_opti93x_free(codec);		return -EBUSY;	}	if (request_dma(dma1, "OPTI93x - 1")) {		snd_printk(KERN_ERR "opti9xx: can't grab DMA1 %d\n", dma1);		snd_opti93x_free(codec);		return -EBUSY;	}	codec->dma1 = chip->dma1;	if (request_dma(dma2, "OPTI93x - 2")) {		snd_printk(KERN_ERR "opti9xx: can't grab DMA2 %d\n", dma2);		snd_opti93x_free(codec);		return -EBUSY;	}	codec->dma2 = chip->dma2;	if (request_irq(chip->irq, snd_opti93x_interrupt, SA_INTERRUPT, DRIVER_NAME" - WSS", codec)) {		snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq);		snd_opti93x_free(codec);		return -EBUSY;	}	codec->card = card;	codec->port = chip->wss_base + 4;	codec->irq = chip->irq;	spin_lock_init(&codec->lock);	codec->hardware = chip->hardware;	codec->chip = chip;	if ((error = snd_opti93x_probe(codec))) {		snd_opti93x_free(codec);		return error;	}	snd_opti93x_init(codec);	/* Register device */	if ((error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, codec, &ops)) < 0) {		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,

⌨️ 快捷键说明

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