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

📄 fm801.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
static snd_pcm_uframes_t snd_fm801_capture_pointer(snd_pcm_substream_t * substream){	fm801_t *chip = snd_pcm_substream_chip(substream);	size_t ptr;	if (!(chip->cap_ctrl & FM801_START))		return 0;	spin_lock(&chip->reg_lock);	ptr = chip->cap_pos + (chip->cap_count - 1) - inw(FM801_REG(chip, CAP_COUNT));	if (inw(FM801_REG(chip, IRQ_STATUS)) & FM801_IRQ_CAPTURE) {		ptr += chip->cap_count;		ptr %= chip->cap_size;	}	spin_unlock(&chip->reg_lock);	return bytes_to_frames(substream->runtime, ptr);}static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id, struct pt_regs *regs){	fm801_t *chip = dev_id;	unsigned short status;	unsigned int tmp;	status = inw(FM801_REG(chip, IRQ_STATUS));	status &= FM801_IRQ_PLAYBACK|FM801_IRQ_CAPTURE|FM801_IRQ_MPU|FM801_IRQ_VOLUME;	if (! status)		return IRQ_NONE;	/* ack first */	outw(status, FM801_REG(chip, IRQ_STATUS));	if (chip->pcm && (status & FM801_IRQ_PLAYBACK) && chip->playback_substream) {		spin_lock(&chip->reg_lock);		chip->ply_buf++;		chip->ply_pos += chip->ply_count;		chip->ply_pos %= chip->ply_size;		tmp = chip->ply_pos + chip->ply_count;		tmp %= chip->ply_size;		outl(chip->ply_buffer + tmp,				(chip->ply_buf & 1) ?					FM801_REG(chip, PLY_BUF1) :					FM801_REG(chip, PLY_BUF2));		spin_unlock(&chip->reg_lock);		snd_pcm_period_elapsed(chip->playback_substream);	}	if (chip->pcm && (status & FM801_IRQ_CAPTURE) && chip->capture_substream) {		spin_lock(&chip->reg_lock);		chip->cap_buf++;		chip->cap_pos += chip->cap_count;		chip->cap_pos %= chip->cap_size;		tmp = chip->cap_pos + chip->cap_count;		tmp %= chip->cap_size;		outl(chip->cap_buffer + tmp,				(chip->cap_buf & 1) ?					FM801_REG(chip, CAP_BUF1) :					FM801_REG(chip, CAP_BUF2));		spin_unlock(&chip->reg_lock);		snd_pcm_period_elapsed(chip->capture_substream);	}	if (chip->rmidi && (status & FM801_IRQ_MPU))		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);	if (status & FM801_IRQ_VOLUME)		;/* TODO */	return IRQ_HANDLED;}static snd_pcm_hardware_t snd_fm801_playback ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_PAUSE |				 SNDRV_PCM_INFO_MMAP_VALID),	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,	.rates =		SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,	.rate_min =		5500,	.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_fm801_capture ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_PAUSE |				 SNDRV_PCM_INFO_MMAP_VALID),	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,	.rates =		SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,	.rate_min =		5500,	.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_fm801_playback_open(snd_pcm_substream_t * substream){	fm801_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	int err;	chip->playback_substream = substream;	runtime->hw = snd_fm801_playback;	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);	if (chip->multichannel) {		runtime->hw.channels_max = 6;		snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels);	}	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)		return err;	return 0;}static int snd_fm801_capture_open(snd_pcm_substream_t * substream){	fm801_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	int err;	chip->capture_substream = substream;	runtime->hw = snd_fm801_capture;	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)		return err;	return 0;}static int snd_fm801_playback_close(snd_pcm_substream_t * substream){	fm801_t *chip = snd_pcm_substream_chip(substream);	chip->playback_substream = NULL;	return 0;}static int snd_fm801_capture_close(snd_pcm_substream_t * substream){	fm801_t *chip = snd_pcm_substream_chip(substream);	chip->capture_substream = NULL;	return 0;}static snd_pcm_ops_t snd_fm801_playback_ops = {	.open =		snd_fm801_playback_open,	.close =	snd_fm801_playback_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_fm801_hw_params,	.hw_free =	snd_fm801_hw_free,	.prepare =	snd_fm801_playback_prepare,	.trigger =	snd_fm801_playback_trigger,	.pointer =	snd_fm801_playback_pointer,};static snd_pcm_ops_t snd_fm801_capture_ops = {	.open =		snd_fm801_capture_open,	.close =	snd_fm801_capture_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_fm801_hw_params,	.hw_free =	snd_fm801_hw_free,	.prepare =	snd_fm801_capture_prepare,	.trigger =	snd_fm801_capture_trigger,	.pointer =	snd_fm801_capture_pointer,};static void snd_fm801_pcm_free(snd_pcm_t *pcm){	fm801_t *chip = pcm->private_data;	chip->pcm = NULL;	snd_pcm_lib_preallocate_free_for_all(pcm);}static int __devinit snd_fm801_pcm(fm801_t *chip, int device, snd_pcm_t ** rpcm){	snd_pcm_t *pcm;	int err;	if (rpcm)		*rpcm = NULL;	if ((err = snd_pcm_new(chip->card, "FM801", device, 1, 1, &pcm)) < 0)		return err;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_fm801_playback_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_fm801_capture_ops);	pcm->private_data = chip;	pcm->private_free = snd_fm801_pcm_free;	pcm->info_flags = 0;	strcpy(pcm->name, "FM801");	chip->pcm = pcm;	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(chip->pci),					      chip->multichannel ? 128*1024 : 64*1024, 128*1024);	if (rpcm)		*rpcm = pcm;	return 0;}/* *  TEA5757 radio */#ifdef TEA575X_RADIO/* 256PCS GPIO numbers */#define TEA_256PCS_DATA			1#define TEA_256PCS_WRITE_ENABLE		2	/* inverted */#define TEA_256PCS_BUS_CLOCK		3static void snd_fm801_tea575x_256pcs_write(tea575x_t *tea, unsigned int val){	fm801_t *chip = tea->private_data;	unsigned short reg;	int i = 25;	spin_lock_irq(&chip->reg_lock);	reg = inw(FM801_REG(chip, GPIO_CTRL));	/* use GPIO lines and set write enable bit */	reg |= FM801_GPIO_GS(TEA_256PCS_DATA) |	       FM801_GPIO_GS(TEA_256PCS_WRITE_ENABLE) |	       FM801_GPIO_GS(TEA_256PCS_BUS_CLOCK);	/* all of lines are in the write direction */	/* clear data and clock lines */	reg &= ~(FM801_GPIO_GD(TEA_256PCS_DATA) |	         FM801_GPIO_GD(TEA_256PCS_WRITE_ENABLE) |	         FM801_GPIO_GD(TEA_256PCS_BUS_CLOCK) |	         FM801_GPIO_GP(TEA_256PCS_DATA) |	         FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK) |		 FM801_GPIO_GP(TEA_256PCS_WRITE_ENABLE));	outw(reg, FM801_REG(chip, GPIO_CTRL));	udelay(1);	while (i--) {		if (val & (1 << i))			reg |= FM801_GPIO_GP(TEA_256PCS_DATA);		else			reg &= ~FM801_GPIO_GP(TEA_256PCS_DATA);		outw(reg, FM801_REG(chip, GPIO_CTRL));		udelay(1);		reg |= FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK);		outw(reg, FM801_REG(chip, GPIO_CTRL));		reg &= ~FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK);		outw(reg, FM801_REG(chip, GPIO_CTRL));		udelay(1);	}	/* and reset the write enable bit */	reg |= FM801_GPIO_GP(TEA_256PCS_WRITE_ENABLE) |	       FM801_GPIO_GP(TEA_256PCS_DATA);	outw(reg, FM801_REG(chip, GPIO_CTRL));	spin_unlock_irq(&chip->reg_lock);}static unsigned int snd_fm801_tea575x_256pcs_read(tea575x_t *tea){	fm801_t *chip = tea->private_data;	unsigned short reg;	unsigned int val = 0;	int i;		spin_lock_irq(&chip->reg_lock);	reg = inw(FM801_REG(chip, GPIO_CTRL));	/* use GPIO lines, set data direction to input */	reg |= FM801_GPIO_GS(TEA_256PCS_DATA) |	       FM801_GPIO_GS(TEA_256PCS_WRITE_ENABLE) |	       FM801_GPIO_GS(TEA_256PCS_BUS_CLOCK) |	       FM801_GPIO_GD(TEA_256PCS_DATA) |	       FM801_GPIO_GP(TEA_256PCS_DATA) |	       FM801_GPIO_GP(TEA_256PCS_WRITE_ENABLE);	/* all of lines are in the write direction, except data */	/* clear data, write enable and clock lines */	reg &= ~(FM801_GPIO_GD(TEA_256PCS_WRITE_ENABLE) |	         FM801_GPIO_GD(TEA_256PCS_BUS_CLOCK) |	         FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK));	for (i = 0; i < 24; i++) {		reg &= ~FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK);		outw(reg, FM801_REG(chip, GPIO_CTRL));		udelay(1);		reg |= FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK);		outw(reg, FM801_REG(chip, GPIO_CTRL));		udelay(1);		val <<= 1;		if (inw(FM801_REG(chip, GPIO_CTRL)) & FM801_GPIO_GP(TEA_256PCS_DATA))			val |= 1;	}	spin_unlock_irq(&chip->reg_lock);	return val;}/* 256PCPR GPIO numbers */#define TEA_256PCPR_BUS_CLOCK		0#define TEA_256PCPR_DATA		1#define TEA_256PCPR_WRITE_ENABLE	2	/* inverted */static void snd_fm801_tea575x_256pcpr_write(tea575x_t *tea, unsigned int val){	fm801_t *chip = tea->private_data;	unsigned short reg;	int i = 25;	spin_lock_irq(&chip->reg_lock);	reg = inw(FM801_REG(chip, GPIO_CTRL));	/* use GPIO lines and set write enable bit */	reg |= FM801_GPIO_GS(TEA_256PCPR_DATA) |	       FM801_GPIO_GS(TEA_256PCPR_WRITE_ENABLE) |	       FM801_GPIO_GS(TEA_256PCPR_BUS_CLOCK);	/* all of lines are in the write direction */	/* clear data and clock lines */	reg &= ~(FM801_GPIO_GD(TEA_256PCPR_DATA) |	         FM801_GPIO_GD(TEA_256PCPR_WRITE_ENABLE) |	         FM801_GPIO_GD(TEA_256PCPR_BUS_CLOCK) |	         FM801_GPIO_GP(TEA_256PCPR_DATA) |	         FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK) |		 FM801_GPIO_GP(TEA_256PCPR_WRITE_ENABLE));	outw(reg, FM801_REG(chip, GPIO_CTRL));	udelay(1);	while (i--) {		if (val & (1 << i))			reg |= FM801_GPIO_GP(TEA_256PCPR_DATA);		else			reg &= ~FM801_GPIO_GP(TEA_256PCPR_DATA);		outw(reg, FM801_REG(chip, GPIO_CTRL));		udelay(1);		reg |= FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK);		outw(reg, FM801_REG(chip, GPIO_CTRL));		reg &= ~FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK);		outw(reg, FM801_REG(chip, GPIO_CTRL));		udelay(1);	}	/* and reset the write enable bit */	reg |= FM801_GPIO_GP(TEA_256PCPR_WRITE_ENABLE) |	       FM801_GPIO_GP(TEA_256PCPR_DATA);	outw(reg, FM801_REG(chip, GPIO_CTRL));	spin_unlock_irq(&chip->reg_lock);}static unsigned int snd_fm801_tea575x_256pcpr_read(tea575x_t *tea){	fm801_t *chip = tea->private_data;	unsigned short reg;	unsigned int val = 0;	int i;		spin_lock_irq(&chip->reg_lock);	reg = inw(FM801_REG(chip, GPIO_CTRL));	/* use GPIO lines, set data direction to input */	reg |= FM801_GPIO_GS(TEA_256PCPR_DATA) |	       FM801_GPIO_GS(TEA_256PCPR_WRITE_ENABLE) |	       FM801_GPIO_GS(TEA_256PCPR_BUS_CLOCK) |	       FM801_GPIO_GD(TEA_256PCPR_DATA) |	       FM801_GPIO_GP(TEA_256PCPR_DATA) |	       FM801_GPIO_GP(TEA_256PCPR_WRITE_ENABLE);	/* all of lines are in the write direction, except data */	/* clear data, write enable and clock lines */	reg &= ~(FM801_GPIO_GD(TEA_256PCPR_WRITE_ENABLE) |	         FM801_GPIO_GD(TEA_256PCPR_BUS_CLOCK) |	         FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK));	for (i = 0; i < 24; i++) {		reg &= ~FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK);		outw(reg, FM801_REG(chip, GPIO_CTRL));		udelay(1);		reg |= FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK);		outw(reg, FM801_REG(chip, GPIO_CTRL));		udelay(1);		val <<= 1;		if (inw(FM801_REG(chip, GPIO_CTRL)) & FM801_GPIO_GP(TEA_256PCPR_DATA))			val |= 1;	}	spin_unlock_irq(&chip->reg_lock);	return val;}/* 64PCR GPIO numbers */#define TEA_64PCR_BUS_CLOCK		0#define TEA_64PCR_WRITE_ENABLE		1	/* inverted */#define TEA_64PCR_DATA			2static void snd_fm801_tea575x_64pcr_write(tea575x_t *tea, unsigned int val){	fm801_t *chip = tea->private_data;	unsigned short reg;	int i = 25;	spin_lock_irq(&chip->reg_lock);	reg = inw(FM801_REG(chip, GPIO_CTRL));	/* use GPIO lines and set write enable bit */	reg |= FM801_GPIO_GS(TEA_64PCR_DATA) |	       FM801_GPIO_GS(TEA_64PCR_WRITE_ENABLE) |	       FM801_GPIO_GS(TEA_64PCR_BUS_CLOCK);	/* all of lines are in the write direction */	/* clear data and clock lines */	reg &= ~(FM801_GPIO_GD(TEA_64PCR_DATA) |	         FM801_GPIO_GD(TEA_64PCR_WRITE_ENABLE) |	         FM801_GPIO_GD(TEA_64PCR_BUS_CLOCK) |	         FM801_GPIO_GP(TEA_64PCR_DATA) |	         FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK) |		 FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE));	outw(reg, FM801_REG(chip, GPIO_CTRL));	udelay(1);	while (i--) {		if (val & (1 << i))			reg |= FM801_GPIO_GP(TEA_64PCR_DATA);		else			reg &= ~FM801_GPIO_GP(TEA_64PCR_DATA);		outw(reg, FM801_REG(chip, GPIO_CTRL));		udelay(1);		reg |= FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK);		outw(reg, FM801_REG(chip, GPIO_CTRL));		reg &= ~FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK);		outw(reg, FM801_REG(chip, GPIO_CTRL));		udelay(1);	}	/* and reset the write enable bit */	reg |= FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE) |	       FM801_GPIO_GP(TEA_64PCR_DATA);	outw(reg, FM801_REG(chip, GPIO_CTRL));	spin_unlock_irq(&chip->reg_lock);}static unsigned int snd_fm801_tea575x_64pcr_read(tea575x_t *tea){	fm801_t *chip = tea->private_data;	unsigned short reg;	unsigned int val = 0;	int i;		spin_lock_irq(&chip->reg_lock);	reg = inw(FM801_REG(chip, GPIO_CTRL));	/* use GPIO lines, set data direction to input */	reg |= FM801_GPIO_GS(TEA_64PCR_DATA) |	       FM801_GPIO_GS(TEA_64PCR_WRITE_ENABLE) |	       FM801_GPIO_GS(TEA_64PCR_BUS_CLOCK) |	       FM801_GPIO_GD(TEA_64PCR_DATA) |	       FM801_GPIO_GP(TEA_64PCR_DATA) |	       FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE);	/* all of lines are in the write direction, except data */	/* clear data, write enable and clock lines */	reg &= ~(FM801_GPIO_GD(TEA_64PCR_WRITE_ENABLE) |	         FM801_GPIO_GD(TEA_64PCR_BUS_CLOCK) |	         FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK));	for (i = 0; i < 24; i++) {		reg &= ~FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK);		outw(reg, FM801_REG(chip, GPIO_CTRL));		udelay(1);		reg |= FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK);		outw(reg, FM801_REG(chip, GPIO_CTRL));		udelay(1);		val <<= 1;		if (inw(FM801_REG(chip, GPIO_CTRL)) & FM801_GPIO_GP(TEA_64PCR_DATA))			val |= 1;	}	spin_unlock_irq(&chip->reg_lock);	return val;}static struct snd_tea575x_ops snd_fm801_tea_ops[3] = {	{		/* 1 = MediaForte 256-PCS */		.write = snd_fm801_tea575x_256pcs_write,		.read = snd_fm801_tea575x_256pcs_read,	},	{		/* 2 = MediaForte 256-PCPR */		.write = snd_fm801_tea575x_256pcpr_write,		.read = snd_fm801_tea575x_256pcpr_read,	},	{		/* 3 = MediaForte 64-PCR */

⌨️ 快捷键说明

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