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

📄 intel8x0m.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			step += ICH_REG_LVI_MASK + 1;		// if (step != 1)		//	snd_printd("step = %d, %d -> %d\n", step, ichdev->civ, civ);		ichdev->civ = civ;	}	ichdev->position += step * ichdev->fragsize1;	ichdev->position %= ichdev->size;	ichdev->lvi += step;	ichdev->lvi &= ICH_REG_LVI_MASK;	iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi);	for (i = 0; i < step; i++) {		ichdev->lvi_frag++;		ichdev->lvi_frag %= ichdev->frags;		ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf +							     ichdev->lvi_frag *							     ichdev->fragsize1);#if 0		printk("new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n",		       ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2],		       ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port),		       inl(port + 4), inb(port + ICH_REG_OFF_CR));#endif		if (--ichdev->ack == 0) {			ichdev->ack = ichdev->ack_reload;			ack = 1;		}	}	if (ack && ichdev->substream) {		spin_unlock(&chip->reg_lock);		snd_pcm_period_elapsed(ichdev->substream);		spin_lock(&chip->reg_lock);	}	iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);}static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id){	struct intel8x0m *chip = dev_id;	struct ichdev *ichdev;	unsigned int status;	unsigned int i;	spin_lock(&chip->reg_lock);	status = igetdword(chip, chip->int_sta_reg);	if (status == 0xffffffff) { /* we are not yet resumed */		spin_unlock(&chip->reg_lock);		return IRQ_NONE;	}	if ((status & chip->int_sta_mask) == 0) {		if (status)			iputdword(chip, chip->int_sta_reg, status);		spin_unlock(&chip->reg_lock);		return IRQ_NONE;	}	for (i = 0; i < chip->bdbars_count; i++) {		ichdev = &chip->ichd[i];		if (status & ichdev->int_sta_mask)			snd_intel8x0_update(chip, ichdev);	}	/* ack them */	iputdword(chip, chip->int_sta_reg, status & chip->int_sta_mask);	spin_unlock(&chip->reg_lock);		return IRQ_HANDLED;}/* *  PCM part */static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd){	struct intel8x0m *chip = snd_pcm_substream_chip(substream);	struct ichdev *ichdev = get_ichdev(substream);	unsigned char val = 0;	unsigned long port = ichdev->reg_offset;	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:	case SNDRV_PCM_TRIGGER_RESUME:		val = ICH_IOCE | ICH_STARTBM;		break;	case SNDRV_PCM_TRIGGER_STOP:	case SNDRV_PCM_TRIGGER_SUSPEND:		val = 0;		break;	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:		val = ICH_IOCE;		break;	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:		val = ICH_IOCE | ICH_STARTBM;		break;	default:		return -EINVAL;	}	iputbyte(chip, port + ICH_REG_OFF_CR, val);	if (cmd == SNDRV_PCM_TRIGGER_STOP) {		/* wait until DMA stopped */		while (!(igetbyte(chip, port + ichdev->roff_sr) & ICH_DCH)) ;		/* reset whole DMA things */		iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS);	}	return 0;}static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream,				  struct snd_pcm_hw_params *hw_params){	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));}static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream){	return snd_pcm_lib_free_pages(substream);}static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *substream){	struct intel8x0m *chip = snd_pcm_substream_chip(substream);	struct ichdev *ichdev = get_ichdev(substream);	size_t ptr1, ptr;	ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << chip->pcm_pos_shift;	if (ptr1 != 0)		ptr = ichdev->fragsize1 - ptr1;	else		ptr = 0;	ptr += ichdev->position;	if (ptr >= ichdev->size)		return 0;	return bytes_to_frames(substream->runtime, ptr);}static int snd_intel8x0m_pcm_prepare(struct snd_pcm_substream *substream){	struct intel8x0m *chip = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	struct ichdev *ichdev = get_ichdev(substream);	ichdev->physbuf = runtime->dma_addr;	ichdev->size = snd_pcm_lib_buffer_bytes(substream);	ichdev->fragsize = snd_pcm_lib_period_bytes(substream);	snd_ac97_write(ichdev->ac97, AC97_LINE1_RATE, runtime->rate);	snd_ac97_write(ichdev->ac97, AC97_LINE1_LEVEL, 0);	snd_intel8x0_setup_periods(chip, ichdev);	return 0;}static struct snd_pcm_hardware snd_intel8x0m_stream ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_MMAP_VALID |				 SNDRV_PCM_INFO_PAUSE |				 SNDRV_PCM_INFO_RESUME),	.formats =		SNDRV_PCM_FMTBIT_S16_LE,	.rates =		SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_KNOT,	.rate_min =		8000,	.rate_max =		16000,	.channels_min =		1,	.channels_max =		1,	.buffer_bytes_max =	64 * 1024,	.period_bytes_min =	32,	.period_bytes_max =	64 * 1024,	.periods_min =		1,	.periods_max =		1024,	.fifo_size =		0,};static int snd_intel8x0m_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev){	static unsigned int rates[] = { 8000,  9600, 12000, 16000 };	static struct snd_pcm_hw_constraint_list hw_constraints_rates = {		.count = ARRAY_SIZE(rates),		.list = rates,		.mask = 0,	};	struct snd_pcm_runtime *runtime = substream->runtime;	int err;	ichdev->substream = substream;	runtime->hw = snd_intel8x0m_stream;	err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,					 &hw_constraints_rates);	if ( err < 0 )		return err;	runtime->private_data = ichdev;	return 0;}static int snd_intel8x0m_playback_open(struct snd_pcm_substream *substream){	struct intel8x0m *chip = snd_pcm_substream_chip(substream);	return snd_intel8x0m_pcm_open(substream, &chip->ichd[ICHD_MDMOUT]);}static int snd_intel8x0m_playback_close(struct snd_pcm_substream *substream){	struct intel8x0m *chip = snd_pcm_substream_chip(substream);	chip->ichd[ICHD_MDMOUT].substream = NULL;	return 0;}static int snd_intel8x0m_capture_open(struct snd_pcm_substream *substream){	struct intel8x0m *chip = snd_pcm_substream_chip(substream);	return snd_intel8x0m_pcm_open(substream, &chip->ichd[ICHD_MDMIN]);}static int snd_intel8x0m_capture_close(struct snd_pcm_substream *substream){	struct intel8x0m *chip = snd_pcm_substream_chip(substream);	chip->ichd[ICHD_MDMIN].substream = NULL;	return 0;}static struct snd_pcm_ops snd_intel8x0m_playback_ops = {	.open =		snd_intel8x0m_playback_open,	.close =	snd_intel8x0m_playback_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_intel8x0_hw_params,	.hw_free =	snd_intel8x0_hw_free,	.prepare =	snd_intel8x0m_pcm_prepare,	.trigger =	snd_intel8x0_pcm_trigger,	.pointer =	snd_intel8x0_pcm_pointer,};static struct snd_pcm_ops snd_intel8x0m_capture_ops = {	.open =		snd_intel8x0m_capture_open,	.close =	snd_intel8x0m_capture_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_intel8x0_hw_params,	.hw_free =	snd_intel8x0_hw_free,	.prepare =	snd_intel8x0m_pcm_prepare,	.trigger =	snd_intel8x0_pcm_trigger,	.pointer =	snd_intel8x0_pcm_pointer,};struct ich_pcm_table {	char *suffix;	struct snd_pcm_ops *playback_ops;	struct snd_pcm_ops *capture_ops;	size_t prealloc_size;	size_t prealloc_max_size;	int ac97_idx;};static int __devinit snd_intel8x0_pcm1(struct intel8x0m *chip, int device,				       struct ich_pcm_table *rec){	struct snd_pcm *pcm;	int err;	char name[32];	if (rec->suffix)		sprintf(name, "Intel ICH - %s", rec->suffix);	else		strcpy(name, "Intel ICH");	err = snd_pcm_new(chip->card, name, device,			  rec->playback_ops ? 1 : 0,			  rec->capture_ops ? 1 : 0, &pcm);	if (err < 0)		return err;	if (rec->playback_ops)		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, rec->playback_ops);	if (rec->capture_ops)		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, rec->capture_ops);	pcm->private_data = chip;	pcm->info_flags = 0;	pcm->dev_class = SNDRV_PCM_CLASS_MODEM;	if (rec->suffix)		sprintf(pcm->name, "%s - %s", chip->card->shortname, rec->suffix);	else		strcpy(pcm->name, chip->card->shortname);	chip->pcm[device] = pcm;	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(chip->pci),					      rec->prealloc_size,					      rec->prealloc_max_size);	return 0;}static struct ich_pcm_table intel_pcms[] __devinitdata = {	{		.suffix = "Modem",		.playback_ops = &snd_intel8x0m_playback_ops,		.capture_ops = &snd_intel8x0m_capture_ops,		.prealloc_size = 32 * 1024,		.prealloc_max_size = 64 * 1024,	},};static int __devinit snd_intel8x0_pcm(struct intel8x0m *chip){	int i, tblsize, device, err;	struct ich_pcm_table *tbl, *rec;#if 1	tbl = intel_pcms;	tblsize = 1;#else	switch (chip->device_type) {	case DEVICE_NFORCE:		tbl = nforce_pcms;		tblsize = ARRAY_SIZE(nforce_pcms);		break;	case DEVICE_ALI:		tbl = ali_pcms;		tblsize = ARRAY_SIZE(ali_pcms);		break;	default:		tbl = intel_pcms;		tblsize = 2;		break;	}#endif	device = 0;	for (i = 0; i < tblsize; i++) {		rec = tbl + i;		if (i > 0 && rec->ac97_idx) {			/* activate PCM only when associated AC'97 codec */			if (! chip->ichd[rec->ac97_idx].ac97)				continue;		}		err = snd_intel8x0_pcm1(chip, device, rec);		if (err < 0)			return err;		device++;	}	chip->pcm_devs = device;	return 0;}	/* *  Mixer part */static void snd_intel8x0_mixer_free_ac97_bus(struct snd_ac97_bus *bus){	struct intel8x0m *chip = bus->private_data;	chip->ac97_bus = NULL;}static void snd_intel8x0_mixer_free_ac97(struct snd_ac97 *ac97){	struct intel8x0m *chip = ac97->private_data;	chip->ac97 = NULL;}static int __devinit snd_intel8x0_mixer(struct intel8x0m *chip, int ac97_clock){	struct snd_ac97_bus *pbus;	struct snd_ac97_template ac97;	struct snd_ac97 *x97;	int err;	unsigned int glob_sta = 0;	static struct snd_ac97_bus_ops ops = {		.write = snd_intel8x0_codec_write,		.read = snd_intel8x0_codec_read,	};	chip->in_ac97_init = 1;		memset(&ac97, 0, sizeof(ac97));	ac97.private_data = chip;	ac97.private_free = snd_intel8x0_mixer_free_ac97;	ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE;	glob_sta = igetdword(chip, ICHREG(GLOB_STA));	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0)		goto __err;	pbus->private_free = snd_intel8x0_mixer_free_ac97_bus;	if (ac97_clock >= 8000 && ac97_clock <= 48000)		pbus->clock = ac97_clock;	chip->ac97_bus = pbus;	ac97.pci = chip->pci;	ac97.num = glob_sta & ICH_SCR ? 1 : 0;	if ((err = snd_ac97_mixer(pbus, &ac97, &x97)) < 0) {		snd_printk(KERN_ERR "Unable to initialize codec #%d\n", ac97.num);		if (ac97.num == 0)			goto __err;		return err;	}	chip->ac97 = x97;	if(ac97_is_modem(x97) && !chip->ichd[ICHD_MDMIN].ac97) {		chip->ichd[ICHD_MDMIN].ac97 = x97;		chip->ichd[ICHD_MDMOUT].ac97 = x97;	}	chip->in_ac97_init = 0;	return 0; __err:	/* clear the cold-reset bit for the next chance */	if (chip->device_type != DEVICE_ALI)		iputdword(chip, ICHREG(GLOB_CNT),			  igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_AC97COLD);	return err;}/* * */static int snd_intel8x0m_ich_chip_init(struct intel8x0m *chip, int probing){	unsigned long end_time;	unsigned int cnt, status, nstatus;		/* put logic to right state */	/* first clear status bits */	status = ICH_RCS | ICH_MIINT | ICH_MOINT;	cnt = igetdword(chip, ICHREG(GLOB_STA));	iputdword(chip, ICHREG(GLOB_STA), cnt & status);	/* ACLink on, 2 channels */	cnt = igetdword(chip, ICHREG(GLOB_CNT));	cnt &= ~(ICH_ACLINK);	/* finish cold or do warm reset */	cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM;	iputdword(chip, ICHREG(GLOB_CNT), cnt);	end_time = (jiffies + (HZ / 4)) + 1;	do {		if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0)			goto __ok;		schedule_timeout_uninterruptible(1);	} while (time_after_eq(end_time, jiffies));	snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n",		   igetdword(chip, ICHREG(GLOB_CNT)));

⌨️ 快捷键说明

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