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

📄 cs4231_lib.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 4 页
字号:
			if (chip->mode & CS4231_MODE_PLAY)				snd_pcm_period_elapsed(chip->playback_substream);			if (chip->mode & CS4231_MODE_RECORD) {				snd_cs4231_overrange(chip);				snd_pcm_period_elapsed(chip->capture_substream);			}		}	} else {		if (status & CS4231_PLAYBACK_IRQ)			snd_pcm_period_elapsed(chip->playback_substream);		if (status & CS4231_RECORD_IRQ) {			snd_cs4231_overrange(chip);			snd_pcm_period_elapsed(chip->capture_substream);		}	}	spin_lock(&chip->reg_lock);	snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);	spin_unlock(&chip->reg_lock);}static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t * substream){	cs4231_t *chip = snd_pcm_substream_chip(substream);	size_t ptr;	if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))		return 0;	ptr = chip->p_dma_size - snd_dma_residue(chip->dma1);	return bytes_to_frames(substream->runtime, ptr);}static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substream){	cs4231_t *chip = snd_pcm_substream_chip(substream);	size_t ptr;		if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))		return 0;	ptr = chip->c_dma_size - snd_dma_residue(chip->dma2);	return bytes_to_frames(substream->runtime, ptr);}/* */static int snd_cs4231_probe(cs4231_t *chip){	unsigned long flags;	int i, id, rev;	unsigned char *ptr;	unsigned int hw;#if 0	snd_cs4231_debug(chip);#endif	id = 0;	for (i = 0; i < 50; i++) {		mb();		if (inb(CS4231P(chip, REGSEL)) & CS4231_INIT)			udelay(2000);		else {			spin_lock_irqsave(&chip->reg_lock, flags);			snd_cs4231_out(chip, CS4231_MISC_INFO, CS4231_MODE2);			id = snd_cs4231_in(chip, CS4231_MISC_INFO) & 0x0f;			spin_unlock_irqrestore(&chip->reg_lock, flags);			if (id == 0x0a)				break;	/* this is valid value */		}	}	snd_printdd("cs4231: port = 0x%lx, id = 0x%x\n", chip->port, id);	if (id != 0x0a)		return -ENODEV;	/* no valid device found */	if (((hw = chip->hardware) & CS4231_HW_TYPE_MASK) == CS4231_HW_DETECT) {		rev = snd_cs4231_in(chip, CS4231_VERSION) & 0xe7;		snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev);		if (rev == 0x80) {			chip->hardware = CS4231_HW_CS4231;		} else if (rev == 0xa0) {			chip->hardware = CS4231_HW_CS4231A;		} else if (rev == 0xa2) {			chip->hardware = CS4231_HW_CS4232;		} else if (rev == 0xb2) {			chip->hardware = CS4231_HW_CS4232A;		} else if (rev == 0x83) {			chip->hardware = CS4231_HW_CS4236;		} else if (rev == 0x03) {			chip->hardware = CS4231_HW_CS4236B;		} else {			snd_printk("unknown CS chip with version 0x%x\n", rev);			return -ENODEV;		/* unknown CS4231 chip? */		}	}	spin_lock_irqsave(&chip->reg_lock, flags);	inb(CS4231P(chip, STATUS));	/* clear any pendings IRQ */	outb(0, CS4231P(chip, STATUS));	mb();	spin_unlock_irqrestore(&chip->reg_lock, flags);	chip->image[CS4231_MISC_INFO] = CS4231_MODE2;	switch (chip->hardware) {	case CS4231_HW_INTERWAVE:		chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3;		break;	case CS4231_HW_CS4235:	case CS4231_HW_CS4236B:	case CS4231_HW_CS4237B:	case CS4231_HW_CS4238B:	case CS4231_HW_CS4239:		if (hw == CS4231_HW_DETECT3)			chip->image[CS4231_MISC_INFO] = CS4231_4236_MODE3;		else			chip->hardware = CS4231_HW_CS4236;		break;	}	chip->image[CS4231_IFACE_CTRL] =	    (chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA) |	    (chip->single_dma ? CS4231_SINGLE_DMA : 0);	chip->image[CS4231_ALT_FEATURE_1] = 0x80;	chip->image[CS4231_ALT_FEATURE_2] = chip->hardware == CS4231_HW_INTERWAVE ? 0xc2 : 0x01;	ptr = (unsigned char *) &chip->image;	snd_cs4231_mce_down(chip);	spin_lock_irqsave(&chip->reg_lock, flags);	for (i = 0; i < 32; i++)	/* ok.. fill all CS4231 registers */		snd_cs4231_out(chip, i, *ptr++);	spin_unlock_irqrestore(&chip->reg_lock, flags);	snd_cs4231_mce_up(chip);	snd_cs4231_mce_down(chip);	mdelay(2);	/* ok.. try check hardware version for CS4236+ chips */	if ((hw & CS4231_HW_TYPE_MASK) == CS4231_HW_DETECT) {		if (chip->hardware == CS4231_HW_CS4236B) {			rev = snd_cs4236_ext_in(chip, CS4236_VERSION);			snd_cs4236_ext_out(chip, CS4236_VERSION, 0xff);			id = snd_cs4236_ext_in(chip, CS4236_VERSION);			snd_cs4236_ext_out(chip, CS4236_VERSION, rev);			snd_printdd("CS4231: ext version; rev = 0x%x, id = 0x%x\n", rev, id);			if ((id & 0x1f) == 0x1d) {	/* CS4235 */				chip->hardware = CS4231_HW_CS4235;				switch (id >> 5) {				case 4:				case 5:				case 6:					break;				default:					snd_printk("unknown CS4235 chip (enhanced version = 0x%x)\n", id);				}			} else if ((id & 0x1f) == 0x0b) {	/* CS4236/B */				switch (id >> 5) {				case 4:				case 5:				case 6:				case 7:					chip->hardware = CS4231_HW_CS4236B;					break;				default:					snd_printk("unknown CS4236 chip (enhanced version = 0x%x)\n", id);				}			} else if ((id & 0x1f) == 0x08) {	/* CS4237B */				chip->hardware = CS4231_HW_CS4237B;				switch (id >> 5) {				case 4:				case 5:				case 6:				case 7:					break;				default:					snd_printk("unknown CS4237B chip (enhanced version = 0x%x)\n", id);				}			} else if ((id & 0x1f) == 0x09) {	/* CS4238B */				chip->hardware = CS4231_HW_CS4238B;				switch (id >> 5) {				case 5:				case 6:				case 7:					break;				default:					snd_printk("unknown CS4238B chip (enhanced version = 0x%x)\n", id);				}			} else if ((id & 0x1f) == 0x1e) {	/* CS4239 */				chip->hardware = CS4231_HW_CS4239;				switch (id >> 5) {				case 4:				case 5:				case 6:					break;				default:					snd_printk("unknown CS4239 chip (enhanced version = 0x%x)\n", id);				}			} else {				snd_printk("unknown CS4236/CS423xB chip (enhanced version = 0x%x)\n", id);			}		}	}	return 0;		/* all things are ok.. */}/* */static snd_pcm_hardware_t snd_cs4231_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:		5510,	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_cs4231_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_KNOT | SNDRV_PCM_RATE_8000_48000,	rate_min:		5510,	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_cs4231_playback_open(snd_pcm_substream_t * substream){	cs4231_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	int err;	runtime->hw = snd_cs4231_playback;	/* hardware bug in InterWave chipset */	if (chip->hardware == CS4231_HW_INTERWAVE && chip->dma1 > 3)	    	runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW;		/* hardware limitation of cheap chips */	if (chip->hardware == CS4231_HW_CS4235 ||	    chip->hardware == CS4231_HW_CS4239)		runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;	snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);	snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);	if (chip->claim_dma) {		if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0)			return err;	}	if ((err = snd_cs4231_open(chip, CS4231_MODE_PLAY)) < 0) {		if (chip->release_dma)			chip->release_dma(chip, chip->dma_private_data, chip->dma1);		snd_free_pages(runtime->dma_area, runtime->dma_bytes);		return err;	}	chip->playback_substream = substream;	snd_pcm_set_sync(substream);	chip->rate_constraint(runtime);	return 0;}static int snd_cs4231_capture_open(snd_pcm_substream_t * substream){	cs4231_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	int err;	runtime->hw = snd_cs4231_capture;	/* hardware limitation of cheap chips */	if (chip->hardware == CS4231_HW_CS4235 ||	    chip->hardware == CS4231_HW_CS4239)		runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;	if (chip->claim_dma) {		if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0)			return err;	}	snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);	snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);	if ((err = snd_cs4231_open(chip, CS4231_MODE_RECORD)) < 0) {		if (chip->release_dma)			chip->release_dma(chip, chip->dma_private_data, chip->dma2);		snd_free_pages(runtime->dma_area, runtime->dma_bytes);		return err;	}	chip->capture_substream = substream;	snd_pcm_set_sync(substream);	chip->rate_constraint(runtime);	return 0;}static int snd_cs4231_playback_close(snd_pcm_substream_t * substream){	cs4231_t *chip = snd_pcm_substream_chip(substream);	chip->playback_substream = NULL;	snd_cs4231_close(chip, CS4231_MODE_PLAY);	return 0;}static int snd_cs4231_capture_close(snd_pcm_substream_t * substream){	cs4231_t *chip = snd_pcm_substream_chip(substream);	chip->capture_substream = NULL;	snd_cs4231_close(chip, CS4231_MODE_RECORD);	return 0;}#ifdef CONFIG_PMstatic void snd_cs4231_suspend(cs4231_t *chip){	int reg;	unsigned long flags;		spin_lock_irqsave(&chip->reg_lock, flags);	for (reg = 0; reg < 32; reg++)		chip->image[reg] = snd_cs4231_in(chip, reg);	spin_unlock_irqrestore(&chip->reg_lock, flags);}static void snd_cs4231_resume(cs4231_t *chip){	int reg;	unsigned long flags;	int timeout;		snd_cs4231_mce_up(chip);	spin_lock_irqsave(&chip->reg_lock, flags);	for (reg = 0; reg < 32; reg++) {		switch (reg) {		case CS4231_VERSION:			break;		default:			snd_cs4231_out(chip, reg, chip->image[reg]);			break;		}	}	spin_unlock_irqrestore(&chip->reg_lock, flags);#if 0	snd_cs4231_mce_down(chip);#else	/* The following is a workaround to avoid freeze after resume on TP600E.	   This is the first half of copy of snd_cs4231_mce_down(), but doesn't	   include rescheduling.  -- iwai	   */	spin_lock_irqsave(&chip->reg_lock, flags);	snd_cs4231_busy_wait(chip);	chip->mce_bit &= ~CS4231_MCE;	timeout = inb(CS4231P(chip, REGSEL));	outb(chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));	if (timeout == 0x80)		snd_printk("down [0x%lx]: serious init problem - codec still busy\n", chip->port);	if ((timeout & CS4231_MCE) == 0 ||	    !(chip->hardware & (CS4231_HW_CS4231_MASK | CS4231_HW_CS4232_MASK))) {		spin_unlock_irqrestore(&chip->reg_lock, flags);		return;	}	snd_cs4231_busy_wait(chip);	spin_unlock_irqrestore(&chip->reg_lock, flags);#endif}static int snd_cs4231_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data){	cs4231_t *chip = snd_magic_cast(cs4231_t, dev->data, return 0);	switch (rqst) {	case PM_SUSPEND:		if (chip->suspend)			(*chip->suspend)(chip);		break;	case PM_RESUME:		if (chip->resume)			(*chip->resume)(chip);		break;	}	return 0;}#endif /* CONFIG_PM */static int snd_cs4231_free(cs4231_t *chip){	if (chip->res_port) {		release_resource(chip->res_port);		kfree_nocheck(chip->res_port);	}	if (chip->res_cport) {		release_resource(chip->res_cport);		kfree_nocheck(chip->res_cport);	}	if (chip->irq >= 0) {		disable_irq(chip->irq);		if (!(chip->hwshare & CS4231_HWSHARE_IRQ))			free_irq(chip->irq, (void *) chip);	}	if (!(chip->hwshare & CS4231_HWSHARE_DMA1) && chip->dma1 >= 0) {		snd_dma_disable(chip->dma1);		free_dma(chip->dma1);	}	if (!(chip->hwshare & CS4231_HWSHARE_DMA2) && chip->dma2 >= 0 && chip->dma2 != chip->dma1) {		snd_dma_disable(chip->dma2);		free_dma(chip->dma2);	}#ifdef CONFIG_PM	if (chip->pm_dev)		pm_unregister(chip->pm_dev);#endif	if (chip->timer)		snd_device_free(chip->card, chip->timer);	snd_magic_kfree(chip);	return 0;}static int snd_cs4231_dev_free(snd_device_t *device){	cs4231_t *chip = snd_magic_cast(cs4231_t, device->device_data, return -ENXIO);	return snd_cs4231_free(chip);	}const char *snd_cs4231_chip_id(cs4231_t *chip){	switch (chip->hardware) {	case CS4231_HW_CS4231:	return "CS4231";	case CS4231_HW_CS4231A: return "CS4231A";	case CS4231_HW_CS4232:	return "CS4232";	case CS4231_HW_CS4232A:	return "CS4232A";	case CS4231_HW_CS4235:	return "CS4235";	case CS4231_HW_CS4236B: return "CS4236B";	case CS4231_HW_CS4237B: return "CS4237B";	case CS4231_HW_CS4238B: return "CS4238B";

⌨️ 快捷键说明

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