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

📄 es1938.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
static void snd_es1938_rate_set(struct es1938 *chip, 				struct snd_pcm_substream *substream,				int mode){	unsigned int bits, div0;	struct snd_pcm_runtime *runtime = substream->runtime;	if (runtime->rate_num == clocks[0].num)		bits = 128 - runtime->rate_den;	else		bits = 256 - runtime->rate_den;	/* set filter register */	div0 = 256 - 7160000*20/(8*82*runtime->rate);			if (mode == DAC2) {		snd_es1938_mixer_write(chip, 0x70, bits);		snd_es1938_mixer_write(chip, 0x72, div0);	} else {		snd_es1938_write(chip, 0xA1, bits);		snd_es1938_write(chip, 0xA2, div0);	}}/* -------------------------------------------------------------------- * Configure Solo1 builtin DMA Controller * --------------------------------------------------------------------*/static void snd_es1938_playback1_setdma(struct es1938 *chip){	outb(0x00, SLIO_REG(chip, AUDIO2MODE));	outl(chip->dma2_start, SLIO_REG(chip, AUDIO2DMAADDR));	outw(0, SLIO_REG(chip, AUDIO2DMACOUNT));	outw(chip->dma2_size, SLIO_REG(chip, AUDIO2DMACOUNT));}static void snd_es1938_playback2_setdma(struct es1938 *chip){	/* Enable DMA controller */	outb(0xc4, SLDM_REG(chip, DMACOMMAND));	/* 1. Master reset */	outb(0, SLDM_REG(chip, DMACLEAR));	/* 2. Mask DMA */	outb(1, SLDM_REG(chip, DMAMASK));	outb(0x18, SLDM_REG(chip, DMAMODE));	outl(chip->dma1_start, SLDM_REG(chip, DMAADDR));	outw(chip->dma1_size - 1, SLDM_REG(chip, DMACOUNT));	/* 3. Unmask DMA */	outb(0, SLDM_REG(chip, DMAMASK));}static void snd_es1938_capture_setdma(struct es1938 *chip){	/* Enable DMA controller */	outb(0xc4, SLDM_REG(chip, DMACOMMAND));	/* 1. Master reset */	outb(0, SLDM_REG(chip, DMACLEAR));	/* 2. Mask DMA */	outb(1, SLDM_REG(chip, DMAMASK));	outb(0x14, SLDM_REG(chip, DMAMODE));	outl(chip->dma1_start, SLDM_REG(chip, DMAADDR));	outw(chip->dma1_size - 1, SLDM_REG(chip, DMACOUNT));	/* 3. Unmask DMA */	outb(0, SLDM_REG(chip, DMAMASK));}/* ---------------------------------------------------------------------- * *                           *** PCM part *** */static int snd_es1938_capture_trigger(struct snd_pcm_substream *substream,				      int cmd){	struct es1938 *chip = snd_pcm_substream_chip(substream);	int val;	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:	case SNDRV_PCM_TRIGGER_RESUME:		val = 0x0f;		chip->active |= ADC1;		break;	case SNDRV_PCM_TRIGGER_STOP:	case SNDRV_PCM_TRIGGER_SUSPEND:		val = 0x00;		chip->active &= ~ADC1;		break;	default:		return -EINVAL;	}	snd_es1938_write(chip, ESS_CMD_DMACONTROL, val);	return 0;}static int snd_es1938_playback1_trigger(struct snd_pcm_substream *substream,					int cmd){	struct es1938 *chip = snd_pcm_substream_chip(substream);	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:	case SNDRV_PCM_TRIGGER_RESUME:		/* According to the documentation this should be:		   0x13 but that value may randomly swap stereo channels */                snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL1, 0x92);                udelay(10);		snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL1, 0x93);                /* This two stage init gives the FIFO -> DAC connection time to                 * settle before first data from DMA flows in.  This should ensure                 * no swapping of stereo channels.  Report a bug if otherwise :-) */		outb(0x0a, SLIO_REG(chip, AUDIO2MODE));		chip->active |= DAC2;		break;	case SNDRV_PCM_TRIGGER_STOP:	case SNDRV_PCM_TRIGGER_SUSPEND:		outb(0, SLIO_REG(chip, AUDIO2MODE));		snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL1, 0);		chip->active &= ~DAC2;		break;	default:		return -EINVAL;	}	return 0;}static int snd_es1938_playback2_trigger(struct snd_pcm_substream *substream,					int cmd){	struct es1938 *chip = snd_pcm_substream_chip(substream);	int val;	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:	case SNDRV_PCM_TRIGGER_RESUME:		val = 5;		chip->active |= DAC1;		break;	case SNDRV_PCM_TRIGGER_STOP:	case SNDRV_PCM_TRIGGER_SUSPEND:		val = 0;		chip->active &= ~DAC1;		break;	default:		return -EINVAL;	}	snd_es1938_write(chip, ESS_CMD_DMACONTROL, val);	return 0;}static int snd_es1938_playback_trigger(struct snd_pcm_substream *substream,				       int cmd){	switch (substream->number) {	case 0:		return snd_es1938_playback1_trigger(substream, cmd);	case 1:		return snd_es1938_playback2_trigger(substream, cmd);	}	snd_BUG();	return -EINVAL;}/* -------------------------------------------------------------------- * First channel for Extended Mode Audio 1 ADC Operation * --------------------------------------------------------------------*/static int snd_es1938_capture_prepare(struct snd_pcm_substream *substream){	struct es1938 *chip = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	int u, is8, mono;	unsigned int size = snd_pcm_lib_buffer_bytes(substream);	unsigned int count = snd_pcm_lib_period_bytes(substream);	chip->dma1_size = size;	chip->dma1_start = runtime->dma_addr;	mono = (runtime->channels > 1) ? 0 : 1;	is8 = snd_pcm_format_width(runtime->format) == 16 ? 0 : 1;	u = snd_pcm_format_unsigned(runtime->format);	chip->dma1_shift = 2 - mono - is8;	snd_es1938_reset_fifo(chip);		/* program type */	snd_es1938_bits(chip, ESS_CMD_ANALOGCONTROL, 0x03, (mono ? 2 : 1));	/* set clock and counters */        snd_es1938_rate_set(chip, substream, ADC1);	count = 0x10000 - count;	snd_es1938_write(chip, ESS_CMD_DMACNTRELOADL, count & 0xff);	snd_es1938_write(chip, ESS_CMD_DMACNTRELOADH, count >> 8);	/* initialize and configure ADC */	snd_es1938_write(chip, ESS_CMD_SETFORMAT2, u ? 0x51 : 0x71);	snd_es1938_write(chip, ESS_CMD_SETFORMAT2, 0x90 | 		       (u ? 0x00 : 0x20) | 		       (is8 ? 0x00 : 0x04) | 		       (mono ? 0x40 : 0x08));	//	snd_es1938_reset_fifo(chip);		/* 11. configure system interrupt controller and DMA controller */	snd_es1938_capture_setdma(chip);	return 0;}/* ------------------------------------------------------------------------------ * Second Audio channel DAC Operation * ------------------------------------------------------------------------------*/static int snd_es1938_playback1_prepare(struct snd_pcm_substream *substream){	struct es1938 *chip = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	int u, is8, mono;	unsigned int size = snd_pcm_lib_buffer_bytes(substream);	unsigned int count = snd_pcm_lib_period_bytes(substream);	chip->dma2_size = size;	chip->dma2_start = runtime->dma_addr;	mono = (runtime->channels > 1) ? 0 : 1;	is8 = snd_pcm_format_width(runtime->format) == 16 ? 0 : 1;	u = snd_pcm_format_unsigned(runtime->format);	chip->dma2_shift = 2 - mono - is8;        snd_es1938_reset_fifo(chip);	/* set clock and counters */        snd_es1938_rate_set(chip, substream, DAC2);	count >>= 1;	count = 0x10000 - count;	snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2TCOUNTL, count & 0xff);	snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2TCOUNTH, count >> 8);	/* initialize and configure Audio 2 DAC */	snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL2, 0x40 | (u ? 0 : 4) |			       (mono ? 0 : 2) | (is8 ? 0 : 1));	/* program DMA */	snd_es1938_playback1_setdma(chip);		return 0;}static int snd_es1938_playback2_prepare(struct snd_pcm_substream *substream){	struct es1938 *chip = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	int u, is8, mono;	unsigned int size = snd_pcm_lib_buffer_bytes(substream);	unsigned int count = snd_pcm_lib_period_bytes(substream);	chip->dma1_size = size;	chip->dma1_start = runtime->dma_addr;	mono = (runtime->channels > 1) ? 0 : 1;	is8 = snd_pcm_format_width(runtime->format) == 16 ? 0 : 1;	u = snd_pcm_format_unsigned(runtime->format);	chip->dma1_shift = 2 - mono - is8;	count = 0x10000 - count; 	/* reset */	snd_es1938_reset_fifo(chip);		snd_es1938_bits(chip, ESS_CMD_ANALOGCONTROL, 0x03, (mono ? 2 : 1));	/* set clock and counters */        snd_es1938_rate_set(chip, substream, DAC1);	snd_es1938_write(chip, ESS_CMD_DMACNTRELOADL, count & 0xff);	snd_es1938_write(chip, ESS_CMD_DMACNTRELOADH, count >> 8);	/* initialized and configure DAC */        snd_es1938_write(chip, ESS_CMD_SETFORMAT, u ? 0x80 : 0x00);        snd_es1938_write(chip, ESS_CMD_SETFORMAT, u ? 0x51 : 0x71);        snd_es1938_write(chip, ESS_CMD_SETFORMAT2, 			 0x90 | (mono ? 0x40 : 0x08) |			 (is8 ? 0x00 : 0x04) | (u ? 0x00 : 0x20));	/* program DMA */	snd_es1938_playback2_setdma(chip);		return 0;}static int snd_es1938_playback_prepare(struct snd_pcm_substream *substream){	switch (substream->number) {	case 0:		return snd_es1938_playback1_prepare(substream);	case 1:		return snd_es1938_playback2_prepare(substream);	}	snd_BUG();	return -EINVAL;}static snd_pcm_uframes_t snd_es1938_capture_pointer(struct snd_pcm_substream *substream){	struct es1938 *chip = snd_pcm_substream_chip(substream);	size_t ptr;	size_t old, new;#if 1	/* This stuff is *needed*, don't ask why - AB */	old = inw(SLDM_REG(chip, DMACOUNT));	while ((new = inw(SLDM_REG(chip, DMACOUNT))) != old)		old = new;	ptr = chip->dma1_size - 1 - new;#else	ptr = inl(SLDM_REG(chip, DMAADDR)) - chip->dma1_start;#endif	return ptr >> chip->dma1_shift;}static snd_pcm_uframes_t snd_es1938_playback1_pointer(struct snd_pcm_substream *substream){	struct es1938 *chip = snd_pcm_substream_chip(substream);	size_t ptr;#if 1	ptr = chip->dma2_size - inw(SLIO_REG(chip, AUDIO2DMACOUNT));#else	ptr = inl(SLIO_REG(chip, AUDIO2DMAADDR)) - chip->dma2_start;#endif	return ptr >> chip->dma2_shift;}static snd_pcm_uframes_t snd_es1938_playback2_pointer(struct snd_pcm_substream *substream){	struct es1938 *chip = snd_pcm_substream_chip(substream);	size_t ptr;	size_t old, new;#if 1	/* This stuff is *needed*, don't ask why - AB */	old = inw(SLDM_REG(chip, DMACOUNT));	while ((new = inw(SLDM_REG(chip, DMACOUNT))) != old)		old = new;	ptr = chip->dma1_size - 1 - new;#else	ptr = inl(SLDM_REG(chip, DMAADDR)) - chip->dma1_start;#endif	return ptr >> chip->dma1_shift;}static snd_pcm_uframes_t snd_es1938_playback_pointer(struct snd_pcm_substream *substream){	switch (substream->number) {	case 0:		return snd_es1938_playback1_pointer(substream);	case 1:		return snd_es1938_playback2_pointer(substream);	}	snd_BUG();	return -EINVAL;}static int snd_es1938_capture_copy(struct snd_pcm_substream *substream,				   int channel,				   snd_pcm_uframes_t pos,				   void __user *dst,				   snd_pcm_uframes_t count){	struct snd_pcm_runtime *runtime = substream->runtime;	struct es1938 *chip = snd_pcm_substream_chip(substream);	pos <<= chip->dma1_shift;	count <<= chip->dma1_shift;	snd_assert(pos + count <= chip->dma1_size, return -EINVAL);	if (pos + count < chip->dma1_size) {		if (copy_to_user(dst, runtime->dma_area + pos + 1, count))			return -EFAULT;	} else {		if (copy_to_user(dst, runtime->dma_area + pos + 1, count - 1))			return -EFAULT;		if (put_user(runtime->dma_area[0], ((unsigned char __user *)dst) + count - 1))			return -EFAULT;	}	return 0;}/* * buffer management */static int snd_es1938_pcm_hw_params(struct snd_pcm_substream *substream,				    struct snd_pcm_hw_params *hw_params){	int err;	if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)		return err;	return 0;}static int snd_es1938_pcm_hw_free(struct snd_pcm_substream *substream){	return snd_pcm_lib_free_pages(substream);}/* ---------------------------------------------------------------------- * Audio1 Capture (ADC) * ----------------------------------------------------------------------*/static struct snd_pcm_hardware snd_es1938_capture ={	.info =			(SNDRV_PCM_INFO_INTERLEAVED |				SNDRV_PCM_INFO_BLOCK_TRANSFER),	.formats =		(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |				 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	.rate_min =		6000,	.rate_max =		48000,	.channels_min =		1,	.channels_max =		2,        .buffer_bytes_max =	0x8000,       /* DMA controller screws on higher values */	.period_bytes_min =	64,	.period_bytes_max =	0x8000,	.periods_min =		1,	.periods_max =		1024,	.fifo_size =		256,};/* ----------------------------------------------------------------------- * Audio2 Playback (DAC) * -----------------------------------------------------------------------*/static struct snd_pcm_hardware snd_es1938_playback ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_MMAP_VALID),	.formats =		(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |				 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	.rate_min =		6000,	.rate_max =		48000,	.channels_min =		1,	.channels_max =		2,        .buffer_bytes_max =	0x8000,       /* DMA controller screws on higher values */	.period_bytes_min =	64,	.period_bytes_max =	0x8000,	.periods_min =		1,	.periods_max =		1024,	.fifo_size =		256,};static int snd_es1938_capture_open(struct snd_pcm_substream *substream){	struct es1938 *chip = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	if (chip->playback2_substream)		return -EAGAIN;	chip->capture_substream = substream;	runtime->hw = snd_es1938_capture;	snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,				      &hw_constraints_clocks);	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0, 0xff00);	return 0;}static int snd_es1938_playback_open(struct snd_pcm_substream *substream){	struct es1938 *chip = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	switch (substream->number) {	case 0:		chip->playback1_substream = substream;

⌨️ 快捷键说明

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