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

📄 riptide.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		goto errout;	}	err = 0;	for (j = 0, time = 0; time < CMDIF_TIMEOUT; j++, time += 2) {		cmdport = &(hwport->port[j % 2]);		if (IS_DATF(cmdport)) {	/* free pending data */			READ_PORT_ULONG(cmdport->data1);			READ_PORT_ULONG(cmdport->data2);		}		if (IS_CMDE(cmdport)) {			if (flags & PARM)	/* put data */				WRITE_PORT_ULONG(cmdport->data2, parm);			WRITE_PORT_ULONG(cmdport->data1, cmd);	/* write cmd */			if ((flags & RESP) && ret) {				while (!IS_DATF(cmdport) &&				       time++ < CMDIF_TIMEOUT)					udelay(10);				if (time < CMDIF_TIMEOUT) {	/* read response */					ret->retlongs[0] =					    READ_PORT_ULONG(cmdport->data1);					ret->retlongs[1] =					    READ_PORT_ULONG(cmdport->data2);				} else {					err = -ENOSYS;					goto errout;				}			}			break;		}		udelay(20);	}	if (time == CMDIF_TIMEOUT) {		err = -ENODATA;		goto errout;	}	spin_unlock_irqrestore(&cif->lock, irqflags);	cif->cmdcnt++;		/* update command statistics */	cif->cmdtime += time;	if (time > cif->cmdtimemax)		cif->cmdtimemax = time;	if (time < cif->cmdtimemin)		cif->cmdtimemin = time;	if ((cif->cmdcnt) % 1000 == 0)		snd_printdd		    ("send cmd %d time: %d mintime: %d maxtime %d err: %d\n",		     cif->cmdcnt, cif->cmdtime, cif->cmdtimemin,		     cif->cmdtimemax, cif->errcnt);	return 0;      errout:	cif->errcnt++;	spin_unlock_irqrestore(&cif->lock, irqflags);	snd_printdd	    ("send cmd %d hw: 0x%x flag: 0x%x cmd: 0x%x parm: 0x%x ret: 0x%x 0x%x CMDE: %d DATF: %d failed %d\n",	     cif->cmdcnt, (int)((void *)&(cmdport->stat) - (void *)hwport),	     flags, cmd, parm, ret ? ret->retlongs[0] : 0,	     ret ? ret->retlongs[1] : 0, IS_CMDE(cmdport), IS_DATF(cmdport),	     err);	return err;}static intsetmixer(struct cmdif *cif, short num, unsigned short rval, unsigned short lval){	union cmdret rptr = CMDRET_ZERO;	int i = 0;	snd_printdd("sent mixer %d: 0x%d 0x%d\n", num, rval, lval);	do {		SEND_SDGV(cif, num, num, rval, lval);		SEND_RDGV(cif, num, num, &rptr);		if (rptr.retwords[0] == lval && rptr.retwords[1] == rval)			return 0;	} while (i++ < MAX_WRITE_RETRY);	snd_printdd("sent mixer failed\n");	return -EIO;}static int getpaths(struct cmdif *cif, unsigned char *o){	unsigned char src[E2SINK_MAX];	unsigned char sink[E2SINK_MAX];	int i, j = 0;	for (i = 0; i < E2SINK_MAX; i++) {		getsourcesink(cif, i, i, &src[i], &sink[i]);		if (sink[i] < E2SINK_MAX) {			o[j++] = sink[i];			o[j++] = i;		}	}	return j;}static intgetsourcesink(struct cmdif *cif, unsigned char source, unsigned char sink,	      unsigned char *a, unsigned char *b){	union cmdret rptr = CMDRET_ZERO;	if (SEND_RSSV(cif, source, sink, &rptr) &&	    SEND_RSSV(cif, source, sink, &rptr))		return -EIO;	*a = rptr.retbytes[0];	*b = rptr.retbytes[1];	snd_printdd("getsourcesink 0x%x 0x%x\n", *a, *b);	return 0;}static intgetsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int *rate){	unsigned char *s;	unsigned int p[2] = { 0, 0 };	int i;	union cmdret rptr = CMDRET_ZERO;	s = intdec;	for (i = 0; i < 2; i++) {		if (*s != 0xff) {			if (SEND_RSRC(cif, *s, &rptr) &&			    SEND_RSRC(cif, *s, &rptr))				return -EIO;			p[i] += rptr.retwords[1];			p[i] *= rptr.retwords[2];			p[i] += rptr.retwords[3];			p[i] /= 65536;		}		s++;	}	if (p[0]) {		if (p[1] != p[0])			snd_printdd("rates differ %d %d\n", p[0], p[1]);		*rate = (unsigned int)p[0];	} else		*rate = (unsigned int)p[1];	snd_printdd("getsampleformat %d %d %d\n", intdec[0], intdec[1], *rate);	return 0;}static intsetsampleformat(struct cmdif *cif,		unsigned char mixer, unsigned char id,		unsigned char channels, unsigned char format){	unsigned char w, ch, sig, order;	snd_printdd	    ("setsampleformat mixer: %d id: %d channels: %d format: %d\n",	     mixer, id, channels, format);	ch = channels == 1;	w = snd_pcm_format_width(format) == 8;	sig = snd_pcm_format_unsigned(format) != 0;	order = snd_pcm_format_big_endian(format) != 0;	if (SEND_SETF(cif, mixer, w, ch, order, sig, id) &&	    SEND_SETF(cif, mixer, w, ch, order, sig, id)) {		snd_printdd("setsampleformat failed\n");		return -EIO;	}	return 0;}static intsetsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int rate){	u32 D, M, N;	union cmdret rptr = CMDRET_ZERO;	int i;	snd_printdd("setsamplerate intdec: %d,%d rate: %d\n", intdec[0],		    intdec[1], rate);	D = 48000;	M = ((rate == 48000) ? 47999 : rate) * 65536;	N = M % D;	M /= D;	for (i = 0; i < 2; i++) {		if (*intdec != 0xff) {			do {				SEND_SSRC(cif, *intdec, D, M, N);				SEND_RSRC(cif, *intdec, &rptr);			} while (rptr.retwords[1] != D &&				 rptr.retwords[2] != M &&				 rptr.retwords[3] != N &&				 i++ < MAX_WRITE_RETRY);			if (i == MAX_WRITE_RETRY) {				snd_printdd("sent samplerate %d: %d failed\n",					    *intdec, rate);				return -EIO;			}		}		intdec++;	}	return 0;}static intgetmixer(struct cmdif *cif, short num, unsigned short *rval,	 unsigned short *lval){	union cmdret rptr = CMDRET_ZERO;	if (SEND_RDGV(cif, num, num, &rptr) && SEND_RDGV(cif, num, num, &rptr))		return -EIO;	*rval = rptr.retwords[0];	*lval = rptr.retwords[1];	snd_printdd("got mixer %d: 0x%d 0x%d\n", num, *rval, *lval);	return 0;}static void riptide_handleirq(unsigned long dev_id){	struct snd_riptide *chip = (void *)dev_id;	struct cmdif *cif = chip->cif;	struct snd_pcm_substream *substream[PLAYBACK_SUBSTREAMS + 1];	struct snd_pcm_runtime *runtime;	struct pcmhw *data = NULL;	unsigned int pos, period_bytes;	struct sgd *c;	int i, j;	unsigned int flag;	if (!cif)		return;	for (i = 0; i < PLAYBACK_SUBSTREAMS; i++)		substream[i] = chip->playback_substream[i];	substream[i] = chip->capture_substream;	for (i = 0; i < PLAYBACK_SUBSTREAMS + 1; i++) {		if (substream[i] &&		    (runtime = substream[i]->runtime) &&		    (data = runtime->private_data) && data->state != ST_STOP) {			pos = 0;			for (j = 0; j < data->pages; j++) {				c = &data->sgdbuf[j];				flag = le32_to_cpu(c->dwStat_Ctl);				if (flag & EOB_STATUS)					pos += le32_to_cpu(c->dwSegLen);				if (flag & EOC_STATUS)					pos += le32_to_cpu(c->dwSegLen);				if ((flag & EOS_STATUS)				    && (data->state == ST_PLAY)) {					data->state = ST_STOP;					snd_printk(KERN_ERR						   "Riptide: DMA stopped unexpectedly\n");				}				c->dwStat_Ctl =				    cpu_to_le32(flag &						~(EOS_STATUS | EOB_STATUS |						  EOC_STATUS));			}			data->pointer += pos;			pos += data->oldpos;			if (data->state != ST_STOP) {				period_bytes =				    frames_to_bytes(runtime,						    runtime->period_size);				snd_printdd				    ("interrupt 0x%x after 0x%lx of 0x%lx frames in period\n",				     READ_AUDIO_STATUS(cif->hwport),				     bytes_to_frames(runtime, pos),				     runtime->period_size);				j = 0;				if (pos >= period_bytes) {					j++;					while (pos >= period_bytes)						pos -= period_bytes;				}				data->oldpos = pos;				if (j > 0)					snd_pcm_period_elapsed(substream[i]);			}		}	}}#ifdef CONFIG_PMstatic int riptide_suspend(struct pci_dev *pci, pm_message_t state){	struct snd_card *card = pci_get_drvdata(pci);	struct snd_riptide *chip = card->private_data;	chip->in_suspend = 1;	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);	snd_pcm_suspend_all(chip->pcm);	snd_ac97_suspend(chip->ac97);	pci_set_power_state(pci, PCI_D3hot);	pci_disable_device(pci);	pci_save_state(pci);	return 0;}static int riptide_resume(struct pci_dev *pci){	struct snd_card *card = pci_get_drvdata(pci);	struct snd_riptide *chip = card->private_data;	pci_restore_state(pci);	pci_enable_device(pci);	pci_set_power_state(pci, PCI_D0);	pci_set_master(pci);	snd_riptide_initialize(chip);	snd_ac97_resume(chip->ac97);	snd_power_change_state(card, SNDRV_CTL_POWER_D0);	chip->in_suspend = 0;	return 0;}#endifstatic int riptide_reset(struct cmdif *cif, struct snd_riptide *chip){	int timeout, tries;	union cmdret rptr = CMDRET_ZERO;	union firmware_version firmware;	int i, j, err, has_firmware;	if (!cif)		return -EINVAL;	cif->cmdcnt = 0;	cif->cmdtime = 0;	cif->cmdtimemax = 0;	cif->cmdtimemin = 0xffffffff;	cif->errcnt = 0;	cif->is_reset = 0;	tries = RESET_TRIES;	has_firmware = 0;	while (has_firmware == 0 && tries-- > 0) {		for (i = 0; i < 2; i++) {			WRITE_PORT_ULONG(cif->hwport->port[i].data1, 0);			WRITE_PORT_ULONG(cif->hwport->port[i].data2, 0);		}		SET_GRESET(cif->hwport);		udelay(100);		UNSET_GRESET(cif->hwport);		udelay(100);		for (timeout = 100000; --timeout; udelay(10)) {			if (IS_READY(cif->hwport) && !IS_GERR(cif->hwport))				break;		}		if (timeout == 0) {			snd_printk(KERN_ERR				   "Riptide: device not ready, audio status: 0x%x ready: %d gerr: %d\n",				   READ_AUDIO_STATUS(cif->hwport),				   IS_READY(cif->hwport), IS_GERR(cif->hwport));			return -EIO;		} else {			snd_printdd			    ("Riptide: audio status: 0x%x ready: %d gerr: %d\n",			     READ_AUDIO_STATUS(cif->hwport),			     IS_READY(cif->hwport), IS_GERR(cif->hwport));		}		SEND_GETV(cif, &rptr);		for (i = 0; i < 4; i++)			firmware.ret.retwords[i] = rptr.retwords[i];		snd_printdd		    ("Firmware version: ASIC: %d CODEC %d AUXDSP %d PROG %d\n",		     firmware.firmware.ASIC, firmware.firmware.CODEC,		     firmware.firmware.AUXDSP, firmware.firmware.PROG);		for (j = 0; j < FIRMWARE_VERSIONS; j++) {			has_firmware = 1;			for (i = 0; i < 4; i++) {				if (firmware_versions[j].ret.retwords[i] !=				    firmware.ret.retwords[i])					has_firmware = 0;			}			if (has_firmware)				break;		}		if (chip != NULL && has_firmware == 0) {			snd_printdd("Writing Firmware\n");			if (!chip->fw_entry) {				if ((err =				     request_firmware(&chip->fw_entry,						      "riptide.hex",						      &chip->pci->dev)) != 0) {					snd_printk(KERN_ERR						   "Riptide: Firmware not available %d\n",						   err);					return -EIO;				}			}			err = loadfirmware(cif, chip->fw_entry->data,					   chip->fw_entry->size);			if (err)				snd_printk(KERN_ERR					   "Riptide: Could not load firmware %d\n",					   err);		}	}	SEND_SACR(cif, 0, AC97_RESET);	SEND_RACR(cif, AC97_RESET, &rptr);	snd_printdd("AC97: 0x%x 0x%x\n", rptr.retlongs[0], rptr.retlongs[1]);	SEND_PLST(cif, 0);	SEND_SLST(cif, 0);	SEND_DLST(cif, 0);	SEND_ALST(cif, 0);	SEND_KDMA(cif);	writearm(cif, 0x301F8, 1, 1);	writearm(cif, 0x301F4, 1, 1);	SEND_LSEL(cif, MODEM_CMD, 0, 0, MODEM_INTDEC, MODEM_MERGER,		  MODEM_SPLITTER, MODEM_MIXER);	setmixer(cif, MODEM_MIXER, 0x7fff, 0x7fff);	alloclbuspath(cif, ARM2LBUS_FIFO13, lbus_play_modem, NULL, NULL);	SEND_LSEL(cif, FM_CMD, 0, 0, FM_INTDEC, FM_MERGER, FM_SPLITTER,		  FM_MIXER);	setmixer(cif, FM_MIXER, 0x7fff, 0x7fff);	writearm(cif, 0x30648 + FM_MIXER * 4, 0x01, 0x00000005);	writearm(cif, 0x301A8, 0x02, 0x00000002);	writearm(cif, 0x30264, 0x08, 0xffffffff);	alloclbuspath(cif, OPL3_SAMPLE, lbus_play_opl3, NULL, NULL);	SEND_SSRC(cif, I2S_INTDEC, 48000,		  ((u32) I2S_RATE * 65536) / 48000,		  ((u32) I2S_RATE * 65536) % 48000);	SEND_LSEL(cif, I2S_CMD0, 0, 0, I2S_INTDEC, I2S_MERGER, I2S_SPLITTER,		  I2S_MIXER);	SEND_SI2S(cif, 1);	alloclbuspath(cif, ARM2LBUS_FIFO0, lbus_play_i2s, NULL, NULL);	alloclbuspath(cif, DIGITAL_MIXER_OUT0, lbus_play_out, NULL, NULL);	alloclbuspath(cif, DIGITAL_MIXER_OUT0, lbus_play_outhp, NULL, NULL);	SET_AIACK(cif->hwport);	SET_AIE(cif->hwport);	SET_AIACK(cif->hwport);	cif->is_reset = 1;	if (chip) {		for (i = 0; i < 4; i++)			chip->firmware.ret.retwords[i] =			    firmware.ret.retwords[i];	}

⌨️ 快捷键说明

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