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

📄 hdsp.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	spinlock_t            lock;	struct snd_pcm_substream *capture_substream;	struct snd_pcm_substream *playback_substream;        struct hdsp_midi      midi[2];	struct tasklet_struct midi_tasklet;	int		      use_midi_tasklet;	int                   precise_ptr;	u32                   control_register;	     /* cached value */	u32                   control2_register;     /* cached value */	u32                   creg_spdif;	u32                   creg_spdif_stream;	int                   clock_source_locked;	char                 *card_name;	     /* digiface/multiface */	enum HDSP_IO_Type     io_type;               /* ditto, but for code use */        unsigned short        firmware_rev;	unsigned short	      state;		     /* stores state bits */	u32		      firmware_cache[24413]; /* this helps recover from accidental iobox power failure */	size_t                period_bytes; 	     /* guess what this is */	unsigned char	      max_channels;	unsigned char	      qs_in_channels;	     /* quad speed mode for H9632 */	unsigned char         ds_in_channels;	unsigned char         ss_in_channels;	    /* different for multiface/digiface */	unsigned char	      qs_out_channels;	    	unsigned char         ds_out_channels;	unsigned char         ss_out_channels;	struct snd_dma_buffer capture_dma_buf;	struct snd_dma_buffer playback_dma_buf;	unsigned char        *capture_buffer;	    /* suitably aligned address */	unsigned char        *playback_buffer;	    /* suitably aligned address */	pid_t                 capture_pid;	pid_t                 playback_pid;	int                   running;	int                   system_sample_rate;	char                 *channel_map;	int                   dev;	int                   irq;	unsigned long         port;        void __iomem         *iobase;	struct snd_card *card;	struct snd_pcm *pcm;	struct snd_hwdep          *hwdep;	struct pci_dev       *pci;	struct snd_kcontrol *spdif_ctl;        unsigned short        mixer_matrix[HDSP_MATRIX_MIXER_SIZE];	unsigned int          dds_value; /* last value written to freq register */};/* These tables map the ALSA channels 1..N to the channels that we   need to use in order to find the relevant channel buffer. RME   refer to this kind of mapping as between "the ADAT channel and   the DMA channel." We index it using the logical audio channel,   and the value is the DMA channel (i.e. channel buffer number)   where the data for that channel can be read/written from/to.*/static char channel_map_df_ss[HDSP_MAX_CHANNELS] = {	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,	18, 19, 20, 21, 22, 23, 24, 25};static char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */	/* Analog */	0, 1, 2, 3, 4, 5, 6, 7, 	/* ADAT 2 */	16, 17, 18, 19, 20, 21, 22, 23, 	/* SPDIF */	24, 25,	-1, -1, -1, -1, -1, -1, -1, -1};static char channel_map_ds[HDSP_MAX_CHANNELS] = {	/* ADAT channels are remapped */	1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23,	/* channels 12 and 13 are S/PDIF */	24, 25,	/* others don't exist */	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};static char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = {	/* ADAT channels */	0, 1, 2, 3, 4, 5, 6, 7,	/* SPDIF */	8, 9,	/* Analog */	10, 11, 	/* AO4S-192 and AI4S-192 extension boards */	12, 13, 14, 15,	/* others don't exist */	-1, -1, -1, -1, -1, -1, -1, -1, 	-1, -1};static char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = {	/* ADAT */	1, 3, 5, 7,	/* SPDIF */	8, 9,	/* Analog */	10, 11, 	/* AO4S-192 and AI4S-192 extension boards */	12, 13, 14, 15,	/* others don't exist */	-1, -1, -1, -1, -1, -1, -1, -1,	-1, -1, -1, -1, -1, -1};static char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = {	/* ADAT is disabled in this mode */	/* SPDIF */	8, 9,	/* Analog */	10, 11,	/* AO4S-192 and AI4S-192 extension boards */	12, 13, 14, 15,	/* others don't exist */	-1, -1, -1, -1, -1, -1, -1, -1,	-1, -1, -1, -1, -1, -1, -1, -1,	-1, -1};static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size){	dmab->dev.type = SNDRV_DMA_TYPE_DEV;	dmab->dev.dev = snd_dma_pci_data(pci);	if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {		if (dmab->bytes >= size)			return 0;	}	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),				size, dmab) < 0)		return -ENOMEM;	return 0;}static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci){	if (dmab->area) {		dmab->dev.dev = NULL; /* make it anonymous */		snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));	}}static struct pci_device_id snd_hdsp_ids[] = {	{		.vendor = PCI_VENDOR_ID_XILINX,		.device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP, 		.subvendor = PCI_ANY_ID,		.subdevice = PCI_ANY_ID,	}, /* RME Hammerfall-DSP */	{ 0, },};MODULE_DEVICE_TABLE(pci, snd_hdsp_ids);/* prototypes */static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp);static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp);static int snd_hdsp_enable_io (struct hdsp *hdsp);static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp);static void snd_hdsp_initialize_channels (struct hdsp *hdsp);static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout);static int hdsp_autosync_ref(struct hdsp *hdsp);static int snd_hdsp_set_defaults(struct hdsp *hdsp);static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp);static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out){	switch (hdsp->io_type) {	case Multiface:	case Digiface:	default:		return (64 * out) + (32 + (in));	case H9632:		return (32 * out) + (16 + (in));	case H9652:		return (52 * out) + (26 + (in));	}}static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out){	switch (hdsp->io_type) {	case Multiface:	case Digiface:	default:		return (64 * out) + in;	case H9632:		return (32 * out) + in;	case H9652:		return (52 * out) + in;	}}static void hdsp_write(struct hdsp *hdsp, int reg, int val){	writel(val, hdsp->iobase + reg);}static unsigned int hdsp_read(struct hdsp *hdsp, int reg){	return readl (hdsp->iobase + reg);}static int hdsp_check_for_iobox (struct hdsp *hdsp){	if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;	if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) {		snd_printk ("Hammerfall-DSP: no Digiface or Multiface connected!\n");		hdsp->state &= ~HDSP_FirmwareLoaded;		return -EIO;	}	return 0;}static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) {	int i;	unsigned long flags;	if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {				snd_printk ("Hammerfall-DSP: loading firmware\n");		hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM);		hdsp_write (hdsp, HDSP_fifoData, 0);				if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {			snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n");			return -EIO;		}				hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);				for (i = 0; i < 24413; ++i) {			hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]);			if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) {				snd_printk ("Hammerfall-DSP: timeout during firmware loading\n");				return -EIO;			}		}		ssleep(3);				if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {			snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n");		    	return -EIO;		}#ifdef SNDRV_BIG_ENDIAN		hdsp->control2_register = HDSP_BIGENDIAN_MODE;#else		hdsp->control2_register = 0;#endif		hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);		snd_printk ("Hammerfall-DSP: finished firmware loading\n");			}	if (hdsp->state & HDSP_InitializationComplete) {		snd_printk(KERN_INFO "Hammerfall-DSP: firmware loaded from cache, restoring defaults\n");		spin_lock_irqsave(&hdsp->lock, flags);		snd_hdsp_set_defaults(hdsp);		spin_unlock_irqrestore(&hdsp->lock, flags); 	}		hdsp->state |= HDSP_FirmwareLoaded;	return 0;}static int hdsp_get_iobox_version (struct hdsp *hdsp){	if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {			hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM);		hdsp_write (hdsp, HDSP_fifoData, 0);		if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0)			return -EIO;		hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);		hdsp_write (hdsp, HDSP_fifoData, 0);		if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT)) {			hdsp->io_type = Multiface;			hdsp_write (hdsp, HDSP_control2Reg, HDSP_VERSION_BIT);			hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);			hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT);		} else {			hdsp->io_type = Digiface;		} 	} else {		/* firmware was already loaded, get iobox type */		if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)			hdsp->io_type = Multiface;		else			hdsp->io_type = Digiface;	}	return 0;}#ifdef HDSP_FW_LOADERstatic int __devinit hdsp_request_fw_loader(struct hdsp *hdsp);#endifstatic int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand){	if (hdsp->io_type == H9652 || hdsp->io_type == H9632)		return 0;	if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {		hdsp->state &= ~HDSP_FirmwareLoaded;		if (! load_on_demand)			return -EIO;		snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n");		/* try to load firmware */		if (! (hdsp->state & HDSP_FirmwareCached)) {#ifdef HDSP_FW_LOADER			if (! hdsp_request_fw_loader(hdsp))				return 0;#endif			snd_printk(KERN_ERR				   "Hammerfall-DSP: No firmware loaded nor "				   "cached, please upload firmware.\n");			return -EIO;		}		if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {			snd_printk(KERN_ERR				   "Hammerfall-DSP: Firmware loading from "				   "cache failed, please upload manually.\n");			return -EIO;		}	}	return 0;}static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout){    	int i;	/* the fifoStatus registers reports on how many words	   are available in the command FIFO.	*/		for (i = 0; i < timeout; i++) {		if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count)			return 0;		/* not very friendly, but we only do this during a firmware		   load and changing the mixer, so we just put up with it.		*/		udelay (100);	}	snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n",		    count, timeout);	return -1;}static int hdsp_read_gain (struct hdsp *hdsp, unsigned int addr){	if (addr >= HDSP_MATRIX_MIXER_SIZE)		return 0;	return hdsp->mixer_matrix[addr];}static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short data){	unsigned int ad;	if (addr >= HDSP_MATRIX_MIXER_SIZE)		return -1;		if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {		/* from martin bjornsen:		   		   "You can only write dwords to the		   mixer memory which contain two		   mixer values in the low and high		   word. So if you want to change		   value 0 you have to read value 1		   from the cache and write both to		   the first dword in the mixer		   memory."		*/		if (hdsp->io_type == H9632 && addr >= 512)			return 0;		if (hdsp->io_type == H9652 && addr >= 1352)			return 0;		hdsp->mixer_matrix[addr] = data;				/* `addr' addresses a 16-bit wide address, but		   the address space accessed via hdsp_write		   uses byte offsets. put another way, addr		   varies from 0 to 1351, but to access the		   corresponding memory location, we need		   to access 0 to 2703 ...		*/		ad = addr/2;			hdsp_write (hdsp, 4096 + (ad*4), 			    (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) + 			    hdsp->mixer_matrix[addr&0x7fe]);				return 0;	} else {		ad = (addr << 16) + data;				if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT))			return -1;		hdsp_write (hdsp, HDSP_fifoData, ad);		hdsp->mixer_matrix[addr] = data;	}	return 0;}static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp){	unsigned long flags;

⌨️ 快捷键说明

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