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

📄 vx222_ops.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Driver for Digigram VX222 V2/Mic soundcards * * VX222-specific low-level routines * * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */#include <sound/driver.h>#include <linux/delay.h>#include <linux/device.h>#include <linux/firmware.h>#include <sound/core.h>#include <sound/control.h>#include <asm/io.h>#include "vx222.h"static int vx2_reg_offset[VX_REG_MAX] = {	[VX_ICR]    = 0x00,	[VX_CVR]    = 0x04,	[VX_ISR]    = 0x08,	[VX_IVR]    = 0x0c,	[VX_RXH]    = 0x14,	[VX_RXM]    = 0x18,	[VX_RXL]    = 0x1c,	[VX_DMA]    = 0x10,	[VX_CDSP]   = 0x20,	[VX_CFG]    = 0x24,	[VX_RUER]   = 0x28,	[VX_DATA]   = 0x2c,	[VX_STATUS] = 0x30,	[VX_LOFREQ] = 0x34,	[VX_HIFREQ] = 0x38,	[VX_CSUER]  = 0x3c,	[VX_SELMIC] = 0x40,	[VX_COMPOT] = 0x44, // Write: POTENTIOMETER ; Read: COMPRESSION LEVEL activate	[VX_SCOMPR] = 0x48, // Read: COMPRESSION THRESHOLD activate	[VX_GLIMIT] = 0x4c, // Read: LEVEL LIMITATION activate	[VX_INTCSR] = 0x4c, // VX_INTCSR_REGISTER_OFFSET	[VX_CNTRL]  = 0x50,		// VX_CNTRL_REGISTER_OFFSET	[VX_GPIOC]  = 0x54,		// VX_GPIOC (new with PLX9030)};static int vx2_reg_index[VX_REG_MAX] = {	[VX_ICR]	= 1,	[VX_CVR]	= 1,	[VX_ISR]	= 1,	[VX_IVR]	= 1,	[VX_RXH]	= 1,	[VX_RXM]	= 1,	[VX_RXL]	= 1,	[VX_DMA]	= 1,	[VX_CDSP]	= 1,	[VX_CFG]	= 1,	[VX_RUER]	= 1,	[VX_DATA]	= 1,	[VX_STATUS]	= 1,	[VX_LOFREQ]	= 1,	[VX_HIFREQ]	= 1,	[VX_CSUER]	= 1,	[VX_SELMIC]	= 1,	[VX_COMPOT]	= 1,	[VX_SCOMPR]	= 1,	[VX_GLIMIT]	= 1,	[VX_INTCSR]	= 0,	/* on the PLX */	[VX_CNTRL]	= 0,	/* on the PLX */	[VX_GPIOC]	= 0,	/* on the PLX */};static inline unsigned long vx2_reg_addr(vx_core_t *_chip, int reg){	struct snd_vx222 *chip = (struct snd_vx222 *)_chip;	return chip->port[vx2_reg_index[reg]] + vx2_reg_offset[reg];}/** * snd_vx_inb - read a byte from the register * @offset: register enum */static unsigned char vx2_inb(vx_core_t *chip, int offset){	return inb(vx2_reg_addr(chip, offset));}/** * snd_vx_outb - write a byte on the register * @offset: the register offset * @val: the value to write */static void vx2_outb(vx_core_t *chip, int offset, unsigned char val){	outb(val, vx2_reg_addr(chip, offset));	//printk("outb: %x -> %x\n", val, vx2_reg_addr(chip, offset));}/** * snd_vx_inl - read a 32bit word from the register * @offset: register enum */static unsigned int vx2_inl(vx_core_t *chip, int offset){	return inl(vx2_reg_addr(chip, offset));}/** * snd_vx_outl - write a 32bit word on the register * @offset: the register enum * @val: the value to write */static void vx2_outl(vx_core_t *chip, int offset, unsigned int val){	// printk("outl: %x -> %x\n", val, vx2_reg_addr(chip, offset));	outl(val, vx2_reg_addr(chip, offset));}/* * redefine macros to call directly */#undef vx_inb#define vx_inb(chip,reg)	vx2_inb((vx_core_t*)(chip), VX_##reg)#undef vx_outb#define vx_outb(chip,reg,val)	vx2_outb((vx_core_t*)(chip), VX_##reg, val)#undef vx_inl#define vx_inl(chip,reg)	vx2_inl((vx_core_t*)(chip), VX_##reg)#undef vx_outl#define vx_outl(chip,reg,val)	vx2_outl((vx_core_t*)(chip), VX_##reg, val)/* * vx_reset_dsp - reset the DSP */#define XX_DSP_RESET_WAIT_TIME		2	/* ms */static void vx2_reset_dsp(vx_core_t *_chip){	struct snd_vx222 *chip = (struct snd_vx222 *)_chip;	/* set the reset dsp bit to 0 */	vx_outl(chip, CDSP, chip->regCDSP & ~VX_CDSP_DSP_RESET_MASK);	snd_vx_delay(_chip, XX_DSP_RESET_WAIT_TIME);	chip->regCDSP |= VX_CDSP_DSP_RESET_MASK;	/* set the reset dsp bit to 1 */	vx_outl(chip, CDSP, chip->regCDSP);}static int vx2_test_xilinx(vx_core_t *_chip){	struct snd_vx222 *chip = (struct snd_vx222 *)_chip;	unsigned int data;	snd_printdd("testing xilinx...\n");	/* This test uses several write/read sequences on TEST0 and TEST1 bits	 * to figure out whever or not the xilinx was correctly loaded	 */	/* We write 1 on CDSP.TEST0. We should get 0 on STATUS.TEST0. */	vx_outl(chip, CDSP, chip->regCDSP | VX_CDSP_TEST0_MASK);	vx_inl(chip, ISR);	data = vx_inl(chip, STATUS);	if ((data & VX_STATUS_VAL_TEST0_MASK) == VX_STATUS_VAL_TEST0_MASK) {		snd_printdd("bad!\n");		return -ENODEV;	}	/* We write 0 on CDSP.TEST0. We should get 1 on STATUS.TEST0. */	vx_outl(chip, CDSP, chip->regCDSP & ~VX_CDSP_TEST0_MASK);	vx_inl(chip, ISR);	data = vx_inl(chip, STATUS);	if (! (data & VX_STATUS_VAL_TEST0_MASK)) {		snd_printdd("bad! #2\n");		return -ENODEV;	}	if (_chip->type == VX_TYPE_BOARD) {		/* not implemented on VX_2_BOARDS */		/* We write 1 on CDSP.TEST1. We should get 0 on STATUS.TEST1. */		vx_outl(chip, CDSP, chip->regCDSP | VX_CDSP_TEST1_MASK);		vx_inl(chip, ISR);		data = vx_inl(chip, STATUS);		if ((data & VX_STATUS_VAL_TEST1_MASK) == VX_STATUS_VAL_TEST1_MASK) {			snd_printdd("bad! #3\n");			return -ENODEV;		}		/* We write 0 on CDSP.TEST1. We should get 1 on STATUS.TEST1. */		vx_outl(chip, CDSP, chip->regCDSP & ~VX_CDSP_TEST1_MASK);		vx_inl(chip, ISR);		data = vx_inl(chip, STATUS);		if (! (data & VX_STATUS_VAL_TEST1_MASK)) {			snd_printdd("bad! #4\n");			return -ENODEV;		}	}	snd_printdd("ok, xilinx fine.\n");	return 0;}/** * vx_setup_pseudo_dma - set up the pseudo dma read/write mode. * @do_write: 0 = read, 1 = set up for DMA write */static void vx2_setup_pseudo_dma(vx_core_t *chip, int do_write){	/* Interrupt mode and HREQ pin enabled for host transmit data transfers	 * (in case of the use of the pseudo-dma facility).	 */	vx_outl(chip, ICR, do_write ? ICR_TREQ : ICR_RREQ);	/* Reset the pseudo-dma register (in case of the use of the	 * pseudo-dma facility).	 */	vx_outl(chip, RESET_DMA, 0);}/* * vx_release_pseudo_dma - disable the pseudo-DMA mode */static inline void vx2_release_pseudo_dma(vx_core_t *chip){	/* HREQ pin disabled. */	vx_outl(chip, ICR, 0);}/* pseudo-dma write */static void vx2_dma_write(vx_core_t *chip, snd_pcm_runtime_t *runtime,			  vx_pipe_t *pipe, int count){	unsigned long port = vx2_reg_addr(chip, VX_DMA);	int offset = pipe->hw_ptr;	u32 *addr = (u32 *)(runtime->dma_area + offset);	snd_assert(count % 4 == 0, return);	vx2_setup_pseudo_dma(chip, 1);	/* Transfer using pseudo-dma.	 */	if (offset + count > pipe->buffer_bytes) {		int length = pipe->buffer_bytes - offset;		count -= length;		length >>= 2; /* in 32bit words */		/* Transfer using pseudo-dma. */		while (length-- > 0) {			outl(cpu_to_le32(*addr), port);			addr++;		}		addr = (u32 *)runtime->dma_area;		pipe->hw_ptr = 0;	}	pipe->hw_ptr += count;	count >>= 2; /* in 32bit words */	/* Transfer using pseudo-dma. */	while (count-- > 0) {		outl(cpu_to_le32(*addr), port);		addr++;	}	vx2_release_pseudo_dma(chip);}/* pseudo dma read */static void vx2_dma_read(vx_core_t *chip, snd_pcm_runtime_t *runtime,			 vx_pipe_t *pipe, int count){	int offset = pipe->hw_ptr;	u32 *addr = (u32 *)(runtime->dma_area + offset);	unsigned long port = vx2_reg_addr(chip, VX_DMA);	snd_assert(count % 4 == 0, return);	vx2_setup_pseudo_dma(chip, 0);	/* Transfer using pseudo-dma.	 */	if (offset + count > pipe->buffer_bytes) {		int length = pipe->buffer_bytes - offset;		count -= length;		length >>= 2; /* in 32bit words */		/* Transfer using pseudo-dma. */		while (length-- > 0)			*addr++ = le32_to_cpu(inl(port));		addr = (u32 *)runtime->dma_area;		pipe->hw_ptr = 0;	}	pipe->hw_ptr += count;	count >>= 2; /* in 32bit words */	/* Transfer using pseudo-dma. */	while (count-- > 0)		*addr++ = le32_to_cpu(inl(port));	vx2_release_pseudo_dma(chip);}#define VX_XILINX_RESET_MASK        0x40000000#define VX_USERBIT0_MASK            0x00000004#define VX_USERBIT1_MASK            0x00000020#define VX_CNTRL_REGISTER_VALUE     0x00172012/* * transfer counts bits to PLX */static int put_xilinx_data(vx_core_t *chip, unsigned int port, unsigned int counts, unsigned char data){	unsigned int i;	for (i = 0; i < counts; i++) {		unsigned int val;		/* set the clock bit to 0. */		val = VX_CNTRL_REGISTER_VALUE & ~VX_USERBIT0_MASK;		vx2_outl(chip, port, val);		vx2_inl(chip, port);		udelay(1);

⌨️ 快捷键说明

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