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

📄 maestro3.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	dsp_in_buffer = s->inst.data + (MINISRC_TMP_BUFFER_SIZE / 2);	dsp_out_buffer = dsp_in_buffer + (dsp_in_size / 2) + 1;	s->dma_size = frames_to_bytes(runtime, runtime->buffer_size);	s->period_size = frames_to_bytes(runtime, runtime->period_size);	s->hwptr = 0;	s->count = 0;#define LO(x) ((x) & 0xffff)#define HI(x) LO((x) >> 16)	/* host dma buffer pointers */	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_HOST_SRC_ADDRL,			  LO(s->buffer_addr));	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_HOST_SRC_ADDRH,			  HI(s->buffer_addr));	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_HOST_SRC_END_PLUS_1L,			  LO(s->buffer_addr + s->dma_size));	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_HOST_SRC_END_PLUS_1H,			  HI(s->buffer_addr + s->dma_size));	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_HOST_SRC_CURRENTL,			  LO(s->buffer_addr));	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_HOST_SRC_CURRENTH,			  HI(s->buffer_addr));#undef LO#undef HI	/* dsp buffers */	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_IN_BUF_BEGIN,			  dsp_in_buffer);	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_IN_BUF_END_PLUS_1,			  dsp_in_buffer + (dsp_in_size / 2));	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_IN_BUF_HEAD,			  dsp_in_buffer);    	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_IN_BUF_TAIL,			  dsp_in_buffer);	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_OUT_BUF_BEGIN,			  dsp_out_buffer);	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_OUT_BUF_END_PLUS_1,			  dsp_out_buffer + (dsp_out_size / 2));	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_OUT_BUF_HEAD,			  dsp_out_buffer);	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_OUT_BUF_TAIL,			  dsp_out_buffer);}static void snd_m3_pcm_setup2(struct snd_m3 *chip, struct m3_dma *s,			      struct snd_pcm_runtime *runtime){	u32 freq;	/* 	 * put us in the lists if we're not already there	 */	if (! s->in_lists) {		s->index[0] = snd_m3_add_list(chip, s->index_list[0],					      s->inst.data >> DP_SHIFT_COUNT);		s->index[1] = snd_m3_add_list(chip, s->index_list[1],					      s->inst.data >> DP_SHIFT_COUNT);		s->index[2] = snd_m3_add_list(chip, s->index_list[2],					      s->inst.data >> DP_SHIFT_COUNT);		s->in_lists = 1;	}	/* write to 'mono' word */	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + SRC3_DIRECTION_OFFSET + 1, 			  runtime->channels == 2 ? 0 : 1);	/* write to '8bit' word */	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + SRC3_DIRECTION_OFFSET + 2, 			  snd_pcm_format_width(runtime->format) == 16 ? 0 : 1);	/* set up dac/adc rate */	freq = ((runtime->rate << 15) + 24000 ) / 48000;	if (freq) 		freq--;	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_FREQUENCY,			  freq);}static const struct play_vals {	u16 addr, val;} pv[] = {	{CDATA_LEFT_VOLUME, ARB_VOLUME},	{CDATA_RIGHT_VOLUME, ARB_VOLUME},	{SRC3_DIRECTION_OFFSET, 0} ,	/* +1, +2 are stereo/16 bit */	{SRC3_DIRECTION_OFFSET + 3, 0x0000}, /* fraction? */	{SRC3_DIRECTION_OFFSET + 4, 0}, /* first l */	{SRC3_DIRECTION_OFFSET + 5, 0}, /* first r */	{SRC3_DIRECTION_OFFSET + 6, 0}, /* second l */	{SRC3_DIRECTION_OFFSET + 7, 0}, /* second r */	{SRC3_DIRECTION_OFFSET + 8, 0}, /* delta l */	{SRC3_DIRECTION_OFFSET + 9, 0}, /* delta r */	{SRC3_DIRECTION_OFFSET + 10, 0x8000}, /* round */	{SRC3_DIRECTION_OFFSET + 11, 0xFF00}, /* higher bute mark */	{SRC3_DIRECTION_OFFSET + 13, 0}, /* temp0 */	{SRC3_DIRECTION_OFFSET + 14, 0}, /* c fraction */	{SRC3_DIRECTION_OFFSET + 15, 0}, /* counter */	{SRC3_DIRECTION_OFFSET + 16, 8}, /* numin */	{SRC3_DIRECTION_OFFSET + 17, 50*2}, /* numout */	{SRC3_DIRECTION_OFFSET + 18, MINISRC_BIQUAD_STAGE - 1}, /* numstage */	{SRC3_DIRECTION_OFFSET + 20, 0}, /* filtertap */	{SRC3_DIRECTION_OFFSET + 21, 0} /* booster */};/* the mode passed should be already shifted and masked */static voidsnd_m3_playback_setup(struct snd_m3 *chip, struct m3_dma *s,		      struct snd_pcm_substream *subs){	unsigned int i;	/*	 * some per client initializers	 */	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + SRC3_DIRECTION_OFFSET + 12,			  s->inst.data + 40 + 8);	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + SRC3_DIRECTION_OFFSET + 19,			  s->inst.code + MINISRC_COEF_LOC);	/* enable or disable low pass filter? */	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + SRC3_DIRECTION_OFFSET + 22,			  subs->runtime->rate > 45000 ? 0xff : 0);    	/* tell it which way dma is going? */	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_DMA_CONTROL,			  DMACONTROL_AUTOREPEAT + DMAC_PAGE3_SELECTOR + DMAC_BLOCKF_SELECTOR);	/*	 * set an armload of static initializers	 */	for (i = 0; i < ARRAY_SIZE(pv); i++) 		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,				  s->inst.data + pv[i].addr, pv[i].val);}/* *    Native record driver  */static const struct rec_vals {	u16 addr, val;} rv[] = {	{CDATA_LEFT_VOLUME, ARB_VOLUME},	{CDATA_RIGHT_VOLUME, ARB_VOLUME},	{SRC3_DIRECTION_OFFSET, 1} ,	/* +1, +2 are stereo/16 bit */	{SRC3_DIRECTION_OFFSET + 3, 0x0000}, /* fraction? */	{SRC3_DIRECTION_OFFSET + 4, 0}, /* first l */	{SRC3_DIRECTION_OFFSET + 5, 0}, /* first r */	{SRC3_DIRECTION_OFFSET + 6, 0}, /* second l */	{SRC3_DIRECTION_OFFSET + 7, 0}, /* second r */	{SRC3_DIRECTION_OFFSET + 8, 0}, /* delta l */	{SRC3_DIRECTION_OFFSET + 9, 0}, /* delta r */	{SRC3_DIRECTION_OFFSET + 10, 0x8000}, /* round */	{SRC3_DIRECTION_OFFSET + 11, 0xFF00}, /* higher bute mark */	{SRC3_DIRECTION_OFFSET + 13, 0}, /* temp0 */	{SRC3_DIRECTION_OFFSET + 14, 0}, /* c fraction */	{SRC3_DIRECTION_OFFSET + 15, 0}, /* counter */	{SRC3_DIRECTION_OFFSET + 16, 50},/* numin */	{SRC3_DIRECTION_OFFSET + 17, 8}, /* numout */	{SRC3_DIRECTION_OFFSET + 18, 0}, /* numstage */	{SRC3_DIRECTION_OFFSET + 19, 0}, /* coef */	{SRC3_DIRECTION_OFFSET + 20, 0}, /* filtertap */	{SRC3_DIRECTION_OFFSET + 21, 0}, /* booster */	{SRC3_DIRECTION_OFFSET + 22, 0xff} /* skip lpf */};static voidsnd_m3_capture_setup(struct snd_m3 *chip, struct m3_dma *s, struct snd_pcm_substream *subs){	unsigned int i;	/*	 * some per client initializers	 */	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + SRC3_DIRECTION_OFFSET + 12,			  s->inst.data + 40 + 8);	/* tell it which way dma is going? */	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_DMA_CONTROL,			  DMACONTROL_DIRECTION + DMACONTROL_AUTOREPEAT + 			  DMAC_PAGE3_SELECTOR + DMAC_BLOCKF_SELECTOR);	/*	 * set an armload of static initializers	 */	for (i = 0; i < ARRAY_SIZE(rv); i++) 		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,				  s->inst.data + rv[i].addr, rv[i].val);}static int snd_m3_pcm_hw_params(struct snd_pcm_substream *substream,				struct snd_pcm_hw_params *hw_params){	struct m3_dma *s = substream->runtime->private_data;	int err;	if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)		return err;	/* set buffer address */	s->buffer_addr = substream->runtime->dma_addr;	if (s->buffer_addr & 0x3) {		snd_printk(KERN_ERR "oh my, not aligned\n");		s->buffer_addr = s->buffer_addr & ~0x3;	}	return 0;}static int snd_m3_pcm_hw_free(struct snd_pcm_substream *substream){	struct m3_dma *s;		if (substream->runtime->private_data == NULL)		return 0;	s = substream->runtime->private_data;	snd_pcm_lib_free_pages(substream);	s->buffer_addr = 0;	return 0;}static intsnd_m3_pcm_prepare(struct snd_pcm_substream *subs){	struct snd_m3 *chip = snd_pcm_substream_chip(subs);	struct snd_pcm_runtime *runtime = subs->runtime;	struct m3_dma *s = runtime->private_data;	snd_assert(s != NULL, return -ENXIO);	if (runtime->format != SNDRV_PCM_FORMAT_U8 &&	    runtime->format != SNDRV_PCM_FORMAT_S16_LE)		return -EINVAL;	if (runtime->rate > 48000 ||	    runtime->rate < 8000)		return -EINVAL;	spin_lock_irq(&chip->reg_lock);	snd_m3_pcm_setup1(chip, s, subs);	if (subs->stream == SNDRV_PCM_STREAM_PLAYBACK)		snd_m3_playback_setup(chip, s, subs);	else		snd_m3_capture_setup(chip, s, subs);	snd_m3_pcm_setup2(chip, s, runtime);	spin_unlock_irq(&chip->reg_lock);	return 0;}/* * get current pointer */static unsigned intsnd_m3_get_pointer(struct snd_m3 *chip, struct m3_dma *s, struct snd_pcm_substream *subs){	u16 hi = 0, lo = 0;	int retry = 10;	u32 addr;	/*	 * try and get a valid answer	 */	while (retry--) {		hi =  snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA,				       s->inst.data + CDATA_HOST_SRC_CURRENTH);		lo = snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA,				      s->inst.data + CDATA_HOST_SRC_CURRENTL);		if (hi == snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA,					   s->inst.data + CDATA_HOST_SRC_CURRENTH))			break;	}	addr = lo | ((u32)hi<<16);	return (unsigned int)(addr - s->buffer_addr);}static snd_pcm_uframes_tsnd_m3_pcm_pointer(struct snd_pcm_substream *subs){	struct snd_m3 *chip = snd_pcm_substream_chip(subs);	unsigned int ptr;	struct m3_dma *s = subs->runtime->private_data;	snd_assert(s != NULL, return 0);	spin_lock(&chip->reg_lock);	ptr = snd_m3_get_pointer(chip, s, subs);	spin_unlock(&chip->reg_lock);	return bytes_to_frames(subs->runtime, ptr);}/* update pointer *//* spinlock held! */static void snd_m3_update_ptr(struct snd_m3 *chip, struct m3_dma *s){	struct snd_pcm_substream *subs = s->substream;	unsigned int hwptr;	int diff;	if (! s->running)		return;	hwptr = snd_m3_get_pointer(chip, s, subs);	/* try to avoid expensive modulo divisions */	if (hwptr >= s->dma_size)		hwptr %= s->dma_size;	diff = s->dma_size + hwptr - s->hwptr;	if (diff >= s->dma_size)		diff %= s->dma_size;	s->hwptr = hwptr;	s->count += diff;	if (s->count >= (signed)s->period_size) {		if (s->count < 2 * (signed)s->period_size)			s->count -= (signed)s->period_size;		else			s->count %= s->period_size;		spin_unlock(&chip->reg_lock);		snd_pcm_period_elapsed(subs);		spin_lock(&chip->reg_lock);	}}static void snd_m3_update_hw_volume(unsigned long private_data){	struct snd_m3 *chip = (struct snd_m3 *) private_data;	int x, val;	unsigned long flags;	/* Figure out which volume control button was pushed,	   based on differences from the default register	   values. */	x = inb(chip->iobase + SHADOW_MIX_REG_VOICE) & 0xee;	/* Reset the volume control registers. */	outb(0x88, chip->iobase + SHADOW_MIX_REG_VOICE);	outb(0x88, chip->iobase + HW_VOL_COUNTER_VOICE);	outb(0x88, chip->iobase + SHADOW_MIX_REG_MASTER);	outb(0x88, chip->iobase + HW_VOL_COUNTER_MASTER);	if (!chip->master_switch || !chip->master_volume)		return;	/* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */	spin_lock_irqsave(&chip->ac97_lock, flags);	val = chip->ac97->regs[AC97_MASTER_VOL];	switch (x) {	case 0x88:		/* mute */		val ^= 0x8000;		chip->ac97->regs[AC97_MASTER_VOL] = val;		outw(val, chip->iobase + CODEC_DATA);		outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,			       &chip->master_switch->id);		break;

⌨️ 快捷键说明

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