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

📄 hdsp.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	u32                   control_register;	     /* cached value */	u32                   control2_register;     /* cached value */	u32                   creg_spdif;	u32                   creg_spdif_stream;	char                 *card_name;	     /* digiface/multiface */	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;	void                 *capture_buffer_unaligned;	 /* original buffer addresses */	void                 *playback_buffer_unaligned; /* original buffer addresses */	unsigned char        *capture_buffer;	    /* suitably aligned address */	unsigned char        *playback_buffer;	    /* suitably aligned address */	dma_addr_t            capture_buffer_addr;	dma_addr_t            playback_buffer_addr;	pid_t                 capture_pid;	pid_t                 playback_pid;	int                   running;        int                   passthru;              /* non-zero if doing pass-thru */	int                   system_sample_rate;	char                 *channel_map;	int                   dev;	int                   irq;	unsigned long         port;	struct resource      *res_port;        unsigned long         iobase;	snd_card_t           *card;	snd_pcm_t            *pcm;	snd_hwdep_t          *hwdep;	struct pci_dev       *pci;	snd_kcontrol_t       *spdif_ctl;        unsigned short        mixer_matrix[HDSP_MATRIX_MIXER_SIZE];};/* 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};#define HDSP_PREALLOCATE_MEMORY	/* via module snd-hdsp_mem */#ifdef HDSP_PREALLOCATE_MEMORYstatic void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture){	struct snd_dma_device pdev;	struct snd_dma_buffer dmbuf;	memset(&pdev, 0, sizeof(pdev));	pdev.type = SNDRV_DMA_TYPE_DEV;	pdev.dev = snd_dma_pci_data(pci);	pdev.id = capture;	dmbuf.bytes = 0;	if (! snd_dma_get_reserved(&pdev, &dmbuf)) {		if (snd_dma_alloc_pages(&pdev, size, &dmbuf) < 0)			return NULL;		snd_dma_set_reserved(&pdev, &dmbuf);	}	*addrp = dmbuf.addr;	return dmbuf.area;}static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture){	struct snd_dma_device pdev;	memset(&pdev, 0, sizeof(pdev));	pdev.type = SNDRV_DMA_TYPE_DEV;	pdev.dev = snd_dma_pci_data(pci);	pdev.id = capture;	snd_dma_free_reserved(&pdev);}#elsestatic void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture){	return snd_malloc_pci_pages(pci, size, addrp);}static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture){	snd_free_pci_pages(pci, size, ptr, addr);}#endifstatic 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 __devinit snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp);static int __devinit snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp);static inline int snd_hdsp_enable_io (hdsp_t *hdsp);static inline void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp);static inline void snd_hdsp_initialize_channels (hdsp_t *hdsp);static inline int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout);static int hdsp_autosync_ref(hdsp_t *hdsp);static int snd_hdsp_set_defaults(hdsp_t *hdsp);static inline void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp);static inline int hdsp_playback_to_output_key (hdsp_t *hdsp, int in, int out){	switch (hdsp->firmware_rev) {	case 0xa:		return (64 * out) + (32 + (in));	case 0x96:	case 0x97:		return (32 * out) + (16 + (in));	default:		return (52 * out) + (26 + (in));	}}static inline int hdsp_input_to_output_key (hdsp_t *hdsp, int in, int out){	switch (hdsp->firmware_rev) {	case 0xa:		return (64 * out) + in;	case 0x96:	case 0x97:		return (32 * out) + in;	default:		return (52 * out) + in;	}}static inline void hdsp_write(hdsp_t *hdsp, int reg, int val){	writel(val, hdsp->iobase + reg);}static inline unsigned int hdsp_read(hdsp_t *hdsp, int reg){	return readl (hdsp->iobase + reg);}static inline int hdsp_check_for_iobox (hdsp_t *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(hdsp_t *hdsp) {	int i;	unsigned long flags;	if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {				snd_printk ("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 ("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 ("timeout during firmware loading\n");				return -EIO;			}		}		if ((1000 / HZ) < 3000) {			set_current_state(TASK_UNINTERRUPTIBLE);			schedule_timeout((3000 * HZ + 999) / 1000);		} else {			mdelay(3000);		}				if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {			snd_printk ("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 ("finished firmware loading\n");			}	if (hdsp->state & HDSP_InitializationComplete) {		snd_printk("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 inline int hdsp_get_iobox_version (hdsp_t *hdsp){	int err;		if (hdsp_check_for_iobox (hdsp)) {		return -EIO;	}	if ((err = snd_hdsp_enable_io(hdsp)) < 0) {		return err;	}			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;}static inline int hdsp_check_for_firmware (hdsp_t *hdsp){	if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;	if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {		snd_printk("firmware not present.\n");		hdsp->state &= ~HDSP_FirmwareLoaded;		return -EIO;	}	return 0;}static inline int hdsp_fifo_wait(hdsp_t *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 ("wait for FIFO status <= %d failed after %d iterations\n",		    count, timeout);	return -1;}static inline int hdsp_read_gain (hdsp_t *hdsp, unsigned int addr){	if (addr >= HDSP_MATRIX_MIXER_SIZE) {		return 0;	}	return hdsp->mixer_matrix[addr];}static inline int hdsp_write_gain(hdsp_t *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 bj鰎nsen:		   		   "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 inline int snd_hdsp_use_is_exclusive(hdsp_t *hdsp){	unsigned long flags;

⌨️ 快捷键说明

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