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

📄 azt3328.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* val = 0xff0d; 41m23.135s (5523,600Hz; -> 5512Hz???) */	/* val = 0xff0e; 28m30.777s (8017Hz; -> 8000Hz???) */	if (channels == 2)		val |= SOUNDFORMAT_FLAG_2CHANNELS;	if (format_width == 16)		val |= SOUNDFORMAT_FLAG_16BIT;	spin_lock_irqsave(&chip->reg_lock, flags);		/* set bitrate/format */	snd_azf3328_codec_outw(chip, reg, val);		/* changing the bitrate/format settings switches off the	 * audio output with an annoying click in case of 8/16bit format change	 * (maybe shutting down DAC/ADC?), thus immediately	 * do some tweaking to reenable it and get rid of the clicking	 * (FIXME: yes, it works, but what exactly am I doing here?? :)	 * FIXME: does this have some side effects for full-duplex	 * or other dramatic side effects? */	if (reg == IDX_IO_PLAY_SOUNDFORMAT) /* only do it for playback */		snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,			snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) |			DMA_PLAY_SOMETHING1 |			DMA_PLAY_SOMETHING2 |			SOMETHING_ALMOST_ALWAYS_SET |			DMA_EPILOGUE_SOMETHING |			DMA_SOMETHING_ELSE		);	spin_unlock_irqrestore(&chip->reg_lock, flags);	snd_azf3328_dbgcallleave();}static voidsnd_azf3328_setdmaa(struct snd_azf3328 *chip,				long unsigned int addr,                                unsigned int count,                                unsigned int size,				int do_recording){	unsigned long flags, portbase;	unsigned int is_running;	snd_azf3328_dbgcallenter();	if (do_recording) {		/* access capture registers, i.e. skip playback reg section */		portbase = chip->codec_port + 0x20;		is_running = chip->is_recording;	} else {		/* access the playback register section */		portbase = chip->codec_port + 0x00;		is_running = chip->is_playing;	}	/* AZF3328 uses a two buffer pointer DMA playback approach */	if (!is_running) {		unsigned long addr_area2;		unsigned long count_areas, count_tmp; /* width 32bit -- overflow!! */		count_areas = size/2;		addr_area2 = addr+count_areas;		count_areas--; /* max. index */		snd_azf3328_dbgplay("set DMA: buf1 %08lx[%lu], buf2 %08lx[%lu]\n", addr, count_areas, addr_area2, count_areas);		/* build combined I/O buffer length word */		count_tmp = count_areas;		count_areas |= (count_tmp << 16);		spin_lock_irqsave(&chip->reg_lock, flags);		outl(addr, portbase + IDX_IO_PLAY_DMA_START_1);		outl(addr_area2, portbase + IDX_IO_PLAY_DMA_START_2);		outl(count_areas, portbase + IDX_IO_PLAY_DMA_LEN_1);		spin_unlock_irqrestore(&chip->reg_lock, flags);	}	snd_azf3328_dbgcallleave();}static intsnd_azf3328_playback_prepare(struct snd_pcm_substream *substream){#if 0	struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;        unsigned int size = snd_pcm_lib_buffer_bytes(substream);	unsigned int count = snd_pcm_lib_period_bytes(substream);#endif	snd_azf3328_dbgcallenter();#if 0	snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT,		runtime->rate,		snd_pcm_format_width(runtime->format),		runtime->channels);	snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, 0);#endif	snd_azf3328_dbgcallleave();	return 0;}static intsnd_azf3328_capture_prepare(struct snd_pcm_substream *substream){#if 0	struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;        unsigned int size = snd_pcm_lib_buffer_bytes(substream);	unsigned int count = snd_pcm_lib_period_bytes(substream);#endif	snd_azf3328_dbgcallenter();#if 0	snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT,		runtime->rate,		snd_pcm_format_width(runtime->format),		runtime->channels);	snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, 1);#endif	snd_azf3328_dbgcallleave();	return 0;}static intsnd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd){	struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	int result = 0;	unsigned int status1;	snd_azf3328_dbgcalls("snd_azf3328_playback_trigger cmd %d\n", cmd);	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:		snd_azf3328_dbgplay("START PLAYBACK\n");		/* mute WaveOut */		snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);		snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT,			runtime->rate,			snd_pcm_format_width(runtime->format),			runtime->channels);		spin_lock(&chip->reg_lock);		/* stop playback */		status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS);		status1 &= ~DMA_RESUME;		snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1);	    		/* FIXME: clear interrupts or what??? */		snd_azf3328_codec_outw(chip, IDX_IO_PLAY_IRQTYPE, 0xffff);		spin_unlock(&chip->reg_lock);		snd_azf3328_setdmaa(chip, runtime->dma_addr,			snd_pcm_lib_period_bytes(substream),			snd_pcm_lib_buffer_bytes(substream),			0);		spin_lock(&chip->reg_lock);#ifdef WIN9X		/* FIXME: enable playback/recording??? */		status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2;		snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1);		/* start playback again */		/* FIXME: what is this value (0x0010)??? */		status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING;		snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1);#else /* NT4 */		snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,			0x0000);		snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,			DMA_PLAY_SOMETHING1);		snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,			DMA_PLAY_SOMETHING1 |			DMA_PLAY_SOMETHING2);		snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,			DMA_RESUME |			SOMETHING_ALMOST_ALWAYS_SET |			DMA_EPILOGUE_SOMETHING |			DMA_SOMETHING_ELSE);#endif		spin_unlock(&chip->reg_lock);		/* now unmute WaveOut */		snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0);		chip->is_playing = 1;		snd_azf3328_dbgplay("STARTED PLAYBACK\n");		break;	case SNDRV_PCM_TRIGGER_RESUME:		snd_azf3328_dbgplay("RESUME PLAYBACK\n");		/* resume playback if we were active */		if (chip->is_playing)			snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,				snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) | DMA_RESUME);		break;	case SNDRV_PCM_TRIGGER_STOP:		snd_azf3328_dbgplay("STOP PLAYBACK\n");		/* mute WaveOut */		snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);		spin_lock(&chip->reg_lock);		/* stop playback */		status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS);		status1 &= ~DMA_RESUME;		snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1);		/* hmm, is this really required? we're resetting the same bit		 * immediately thereafter... */		status1 |= DMA_PLAY_SOMETHING1;		snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1);		status1 &= ~DMA_PLAY_SOMETHING1;		snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1);		spin_unlock(&chip->reg_lock);	    		/* now unmute WaveOut */		snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0);		chip->is_playing = 0;		snd_azf3328_dbgplay("STOPPED PLAYBACK\n");		break;	case SNDRV_PCM_TRIGGER_SUSPEND:		snd_azf3328_dbgplay("SUSPEND PLAYBACK\n");		/* make sure playback is stopped */		snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,			snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) & ~DMA_RESUME);		break;        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:		snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n");                break;        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:		snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n");                break;        default:		printk(KERN_ERR "FIXME: unknown trigger mode!\n");                return -EINVAL;	}		snd_azf3328_dbgcallleave();	return result;}/* this is just analogous to playback; I'm not quite sure whether recording * should actually be triggered like that */static intsnd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd){	struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	int result = 0;	unsigned int status1;	snd_azf3328_dbgcalls("snd_azf3328_capture_trigger cmd %d\n", cmd);        switch (cmd) {        case SNDRV_PCM_TRIGGER_START:		snd_azf3328_dbgplay("START CAPTURE\n");		snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT,			runtime->rate,			snd_pcm_format_width(runtime->format),			runtime->channels);		spin_lock(&chip->reg_lock);		/* stop recording */		status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS);		status1 &= ~DMA_RESUME;		snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);	    		/* FIXME: clear interrupts or what??? */		snd_azf3328_codec_outw(chip, IDX_IO_REC_IRQTYPE, 0xffff);		spin_unlock(&chip->reg_lock);		snd_azf3328_setdmaa(chip, runtime->dma_addr,			snd_pcm_lib_period_bytes(substream),			snd_pcm_lib_buffer_bytes(substream),			1);		spin_lock(&chip->reg_lock);#ifdef WIN9X		/* FIXME: enable playback/recording??? */		status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2;		snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);		/* start capture again */		/* FIXME: what is this value (0x0010)??? */		status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING;		snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);#else		snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,			0x0000);		snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,			DMA_PLAY_SOMETHING1);		snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,			DMA_PLAY_SOMETHING1 |			DMA_PLAY_SOMETHING2);		snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,			DMA_RESUME |			SOMETHING_ALMOST_ALWAYS_SET |			DMA_EPILOGUE_SOMETHING |			DMA_SOMETHING_ELSE);#endif		spin_unlock(&chip->reg_lock);		chip->is_recording = 1;		snd_azf3328_dbgplay("STARTED CAPTURE\n");		break;	case SNDRV_PCM_TRIGGER_RESUME:		snd_azf3328_dbgplay("RESUME CAPTURE\n");		/* resume recording if we were active */		if (chip->is_recording)			snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,				snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) | DMA_RESUME);		break;        case SNDRV_PCM_TRIGGER_STOP:		snd_azf3328_dbgplay("STOP CAPTURE\n");		spin_lock(&chip->reg_lock);		/* stop recording */		status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS);		status1 &= ~DMA_RESUME;		snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);		status1 |= DMA_PLAY_SOMETHING1;		snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);		status1 &= ~DMA_PLAY_SOMETHING1;		snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);		spin_unlock(&chip->reg_lock);	    		chip->is_recording = 0;		snd_azf3328_dbgplay("STOPPED CAPTURE\n");		break;	case SNDRV_PCM_TRIGGER_SUSPEND:		snd_azf3328_dbgplay("SUSPEND CAPTURE\n");		/* make sure recording is stopped */		snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,			snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) & ~DMA_RESUME);		break;        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:		snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n");                break;        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:		snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n");                break;        default:		printk(KERN_ERR "FIXME: unknown trigger mode!\n");                return -EINVAL;	}		snd_azf3328_dbgcallleave();	return result;}static snd_pcm_uframes_tsnd_azf3328_playback_pointer(struct snd_pcm_substream *substream){	struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);	unsigned long bufptr, result;	snd_pcm_uframes_t frmres;#ifdef QUERY_HARDWARE	bufptr = inl(chip->codec_port+IDX_IO_PLAY_DMA_START_1);#else	bufptr = substream->runtime->dma_addr;#endif	result = inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS);	/* calculate offset */	result -= bufptr;	frmres = bytes_to_frames( substream->runtime, result);	snd_azf3328_dbgplay("PLAY @ 0x%8lx, frames %8ld\n", result, frmres);	return frmres;}static snd_pcm_uframes_tsnd_azf3328_capture_pointer(struct snd_pcm_substream *substream){	struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);	unsigned long bufptr, result;	snd_pcm_uframes_t frmres;#ifdef QUERY_HARDWARE	bufptr = inl(chip->codec_port+IDX_IO_REC_DMA_START_1);#else	bufptr = substream->runtime->dma_addr;#endif	result = inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS);	/* calculate offset */	result -= bufptr;	frmres = bytes_to_frames( substream->runtime, result);	snd_azf3328_dbgplay("REC  @ 0x%8lx, frames %8ld\n", result, frmres);	return frmres;

⌨️ 快捷键说明

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