2005-04-17 02:20:36 +04:00
/*
* Driver for Digigram VX soundcards
*
* Hardware core part
*
* 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
*/
# ifndef __SOUND_VX_COMMON_H
# define __SOUND_VX_COMMON_H
# include <sound/pcm.h>
# include <sound/hwdep.h>
# include <linux/interrupt.h>
# if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
# if !defined(CONFIG_USE_VXLOADER) && !defined(CONFIG_SND_VX_LIB) /* built-in kernel */
# define SND_VX_FW_LOADER /* use the standard firmware loader */
# endif
# endif
struct firmware ;
struct device ;
typedef struct snd_vx_core vx_core_t ;
typedef struct vx_pipe vx_pipe_t ;
# define VX_DRIVER_VERSION 0x010000 /* 1.0.0 */
/*
*/
# define SIZE_MAX_CMD 0x10
# define SIZE_MAX_STATUS 0x10
struct vx_rmh {
u16 LgCmd ; /* length of the command to send (WORDs) */
u16 LgStat ; /* length of the status received (WORDs) */
u32 Cmd [ SIZE_MAX_CMD ] ;
u32 Stat [ SIZE_MAX_STATUS ] ;
u16 DspStat ; /* status type, RMP_SSIZE_XXX */
} ;
typedef u64 pcx_time_t ;
# define VX_MAX_PIPES 16
# define VX_MAX_PERIODS 32
# define VX_MAX_CODECS 2
struct vx_ibl_info {
int size ; /* the current IBL size (0 = query) in bytes */
int max_size ; /* max. IBL size in bytes */
int min_size ; /* min. IBL size in bytes */
int granularity ; /* granularity */
} ;
struct vx_pipe {
int number ;
unsigned int is_capture : 1 ;
unsigned int data_mode : 1 ;
unsigned int running : 1 ;
unsigned int prepared : 1 ;
int channels ;
unsigned int differed_type ;
pcx_time_t pcx_time ;
snd_pcm_substream_t * substream ;
int hbuf_size ; /* H-buffer size in bytes */
int buffer_bytes ; /* the ALSA pcm buffer size in bytes */
int period_bytes ; /* the ALSA pcm period size in bytes */
int hw_ptr ; /* the current hardware pointer in bytes */
int position ; /* the current position in frames (playback only) */
int transferred ; /* the transferred size (per period) in frames */
int align ; /* size of alignment */
u64 cur_count ; /* current sample position (for playback) */
unsigned int references ; /* an output pipe may be used for monitoring and/or playback */
vx_pipe_t * monitoring_pipe ; /* pointer to the monitoring pipe (capture pipe only)*/
struct tasklet_struct start_tq ;
} ;
struct snd_vx_ops {
/* low-level i/o */
unsigned char ( * in8 ) ( vx_core_t * chip , int reg ) ;
unsigned int ( * in32 ) ( vx_core_t * chip , int reg ) ;
void ( * out8 ) ( vx_core_t * chip , int reg , unsigned char val ) ;
void ( * out32 ) ( vx_core_t * chip , int reg , unsigned int val ) ;
/* irq */
int ( * test_and_ack ) ( vx_core_t * chip ) ;
void ( * validate_irq ) ( vx_core_t * chip , int enable ) ;
/* codec */
void ( * write_codec ) ( vx_core_t * chip , int codec , unsigned int data ) ;
void ( * akm_write ) ( vx_core_t * chip , int reg , unsigned int data ) ;
void ( * reset_codec ) ( vx_core_t * chip ) ;
void ( * change_audio_source ) ( vx_core_t * chip , int src ) ;
void ( * set_clock_source ) ( vx_core_t * chp , int src ) ;
/* chip init */
int ( * load_dsp ) ( vx_core_t * chip , int idx , const struct firmware * fw ) ;
void ( * reset_dsp ) ( vx_core_t * chip ) ;
void ( * reset_board ) ( vx_core_t * chip , int cold_reset ) ;
int ( * add_controls ) ( vx_core_t * chip ) ;
/* pcm */
void ( * dma_write ) ( vx_core_t * chip , snd_pcm_runtime_t * runtime ,
vx_pipe_t * pipe , int count ) ;
void ( * dma_read ) ( vx_core_t * chip , snd_pcm_runtime_t * runtime ,
vx_pipe_t * pipe , int count ) ;
} ;
struct snd_vx_hardware {
const char * name ;
int type ; /* VX_TYPE_XXX */
/* hardware specs */
unsigned int num_codecs ;
unsigned int num_ins ;
unsigned int num_outs ;
unsigned int output_level_max ;
} ;
/* hwdep id string */
# define SND_VX_HWDEP_ID "VX Loader"
/* hardware type */
enum {
/* VX222 PCI */
VX_TYPE_BOARD , /* old VX222 PCI */
VX_TYPE_V2 , /* VX222 V2 PCI */
VX_TYPE_MIC , /* VX222 Mic PCI */
/* VX-pocket */
VX_TYPE_VXPOCKET , /* VXpocket V2 */
VX_TYPE_VXP440 , /* VXpocket 440 */
VX_TYPE_NUMS
} ;
/* chip status */
enum {
VX_STAT_XILINX_LOADED = ( 1 < < 0 ) , /* devices are registered */
VX_STAT_DEVICE_INIT = ( 1 < < 1 ) , /* devices are registered */
VX_STAT_CHIP_INIT = ( 1 < < 2 ) , /* all operational */
VX_STAT_IN_SUSPEND = ( 1 < < 10 ) , /* in suspend phase */
VX_STAT_IS_STALE = ( 1 < < 15 ) /* device is stale */
} ;
/* min/max values for analog output for old codecs */
# define VX_ANALOG_OUT_LEVEL_MAX 0xe3
struct snd_vx_core {
/* ALSA stuff */
snd_card_t * card ;
snd_pcm_t * pcm [ VX_MAX_CODECS ] ;
int type ; /* VX_TYPE_XXX */
int irq ;
/* ports are defined externally */
/* low-level functions */
struct snd_vx_hardware * hw ;
struct snd_vx_ops * ops ;
spinlock_t lock ;
spinlock_t irq_lock ;
struct tasklet_struct tq ;
unsigned int chip_status ;
unsigned int pcm_running ;
struct device * dev ;
snd_hwdep_t * hwdep ;
struct vx_rmh irq_rmh ; /* RMH used in interrupts */
unsigned int audio_info ; /* see VX_AUDIO_INFO */
unsigned int audio_ins ;
unsigned int audio_outs ;
struct vx_pipe * * playback_pipes ;
struct vx_pipe * * capture_pipes ;
/* clock and audio sources */
unsigned int audio_source ; /* current audio input source */
unsigned int audio_source_target ;
unsigned int clock_mode ; /* clock mode (VX_CLOCK_MODE_XXX) */
unsigned int clock_source ; /* current clock source (INTERNAL_QUARTZ or UER_SYNC) */
unsigned int freq ; /* current frequency */
unsigned int freq_detected ; /* detected frequency from digital in */
unsigned int uer_detected ; /* VX_UER_MODE_XXX */
unsigned int uer_bits ; /* IEC958 status bits */
struct vx_ibl_info ibl ; /* IBL information */
/* mixer setting */
int output_level [ VX_MAX_CODECS ] [ 2 ] ; /* analog output level */
int audio_gain [ 2 ] [ 4 ] ; /* digital audio level (playback/capture) */
unsigned char audio_active [ 4 ] ; /* mute/unmute on digital playback */
int audio_monitor [ 4 ] ; /* playback hw-monitor level */
unsigned char audio_monitor_active [ 4 ] ; /* playback hw-monitor mute/unmute */
struct semaphore mixer_mutex ;
const struct firmware * firmware [ 4 ] ; /* loaded firmware data */
} ;
/*
* constructor
*/
vx_core_t * snd_vx_create ( snd_card_t * card , struct snd_vx_hardware * hw ,
struct snd_vx_ops * ops , int extra_size ) ;
int snd_vx_setup_firmware ( vx_core_t * chip ) ;
int snd_vx_load_boot_image ( vx_core_t * chip , const struct firmware * dsp ) ;
int snd_vx_dsp_boot ( vx_core_t * chip , const struct firmware * dsp ) ;
int snd_vx_dsp_load ( vx_core_t * chip , const struct firmware * dsp ) ;
void snd_vx_free_firmware ( vx_core_t * chip ) ;
/*
* interrupt handler ; exported for pcmcia
*/
irqreturn_t snd_vx_irq_handler ( int irq , void * dev , struct pt_regs * regs ) ;
/*
* lowlevel functions
*/
2005-07-27 22:46:09 +04:00
static inline int vx_test_and_ack ( vx_core_t * chip )
2005-04-17 02:20:36 +04:00
{
snd_assert ( chip - > ops - > test_and_ack , return - ENXIO ) ;
return chip - > ops - > test_and_ack ( chip ) ;
}
2005-07-27 22:46:09 +04:00
static inline void vx_validate_irq ( vx_core_t * chip , int enable )
2005-04-17 02:20:36 +04:00
{
snd_assert ( chip - > ops - > validate_irq , return ) ;
chip - > ops - > validate_irq ( chip , enable ) ;
}
2005-07-27 22:46:09 +04:00
static inline unsigned char snd_vx_inb ( vx_core_t * chip , int reg )
2005-04-17 02:20:36 +04:00
{
snd_assert ( chip - > ops - > in8 , return 0 ) ;
return chip - > ops - > in8 ( chip , reg ) ;
}
2005-07-27 22:46:09 +04:00
static inline unsigned int snd_vx_inl ( vx_core_t * chip , int reg )
2005-04-17 02:20:36 +04:00
{
snd_assert ( chip - > ops - > in32 , return 0 ) ;
return chip - > ops - > in32 ( chip , reg ) ;
}
2005-07-27 22:46:09 +04:00
static inline void snd_vx_outb ( vx_core_t * chip , int reg , unsigned char val )
2005-04-17 02:20:36 +04:00
{
snd_assert ( chip - > ops - > out8 , return ) ;
chip - > ops - > out8 ( chip , reg , val ) ;
}
2005-07-27 22:46:09 +04:00
static inline void snd_vx_outl ( vx_core_t * chip , int reg , unsigned int val )
2005-04-17 02:20:36 +04:00
{
snd_assert ( chip - > ops - > out32 , return ) ;
chip - > ops - > out32 ( chip , reg , val ) ;
}
# define vx_inb(chip,reg) snd_vx_inb(chip, VX_##reg)
# define vx_outb(chip,reg,val) snd_vx_outb(chip, VX_##reg,val)
# define vx_inl(chip,reg) snd_vx_inl(chip, VX_##reg)
# define vx_outl(chip,reg,val) snd_vx_outl(chip, VX_##reg,val)
void snd_vx_delay ( vx_core_t * chip , int msec ) ;
static inline void vx_reset_dsp ( vx_core_t * chip )
{
snd_assert ( chip - > ops - > reset_dsp , return ) ;
chip - > ops - > reset_dsp ( chip ) ;
}
int vx_send_msg ( vx_core_t * chip , struct vx_rmh * rmh ) ;
int vx_send_msg_nolock ( vx_core_t * chip , struct vx_rmh * rmh ) ;
int vx_send_rih ( vx_core_t * chip , int cmd ) ;
int vx_send_rih_nolock ( vx_core_t * chip , int cmd ) ;
void vx_reset_codec ( vx_core_t * chip , int cold_reset ) ;
/*
* check the bit on the specified register
* returns zero if a bit matches , or a negative error code .
* exported for vxpocket driver
*/
int snd_vx_check_reg_bit ( vx_core_t * chip , int reg , int mask , int bit , int time ) ;
# define vx_check_isr(chip,mask,bit,time) snd_vx_check_reg_bit(chip, VX_ISR, mask, bit, time)
# define vx_wait_isr_bit(chip,bit) vx_check_isr(chip, bit, bit, 200)
# define vx_wait_for_rx_full(chip) vx_wait_isr_bit(chip, ISR_RX_FULL)
/*
* pseudo - DMA transfer
*/
2005-07-27 22:46:09 +04:00
static inline void vx_pseudo_dma_write ( vx_core_t * chip , snd_pcm_runtime_t * runtime ,
2005-04-17 02:20:36 +04:00
vx_pipe_t * pipe , int count )
{
snd_assert ( chip - > ops - > dma_write , return ) ;
chip - > ops - > dma_write ( chip , runtime , pipe , count ) ;
}
2005-07-27 22:46:09 +04:00
static inline void vx_pseudo_dma_read ( vx_core_t * chip , snd_pcm_runtime_t * runtime ,
2005-04-17 02:20:36 +04:00
vx_pipe_t * pipe , int count )
{
snd_assert ( chip - > ops - > dma_read , return ) ;
chip - > ops - > dma_read ( chip , runtime , pipe , count ) ;
}
/* error with hardware code,
* the return value is - ( VX_ERR_MASK | actual - hw - error - code )
*/
# define VX_ERR_MASK 0x1000000
# define vx_get_error(err) (-(err) & ~VX_ERR_MASK)
/*
* pcm stuff
*/
int snd_vx_pcm_new ( vx_core_t * chip ) ;
void vx_pcm_update_intr ( vx_core_t * chip , unsigned int events ) ;
/*
* mixer stuff
*/
int snd_vx_mixer_new ( vx_core_t * chip ) ;
void vx_toggle_dac_mute ( vx_core_t * chip , int mute ) ;
int vx_sync_audio_source ( vx_core_t * chip ) ;
int vx_set_monitor_level ( vx_core_t * chip , int audio , int level , int active ) ;
/*
* IEC958 & clock stuff
*/
void vx_set_iec958_status ( vx_core_t * chip , unsigned int bits ) ;
int vx_set_clock ( vx_core_t * chip , unsigned int freq ) ;
void vx_set_internal_clock ( vx_core_t * chip , unsigned int freq ) ;
int vx_change_frequency ( vx_core_t * chip ) ;
/*
* hardware constants
*/
# define vx_has_new_dsp(chip) ((chip)->type != VX_TYPE_BOARD)
# define vx_is_pcmcia(chip) ((chip)->type >= VX_TYPE_VXPOCKET)
/* audio input source */
enum {
VX_AUDIO_SRC_DIGITAL ,
VX_AUDIO_SRC_LINE ,
VX_AUDIO_SRC_MIC
} ;
/* clock source */
enum {
INTERNAL_QUARTZ ,
UER_SYNC
} ;
/* clock mode */
enum {
VX_CLOCK_MODE_AUTO , /* depending on the current audio source */
VX_CLOCK_MODE_INTERNAL , /* fixed to internal quartz */
VX_CLOCK_MODE_EXTERNAL /* fixed to UER sync */
} ;
/* SPDIF/UER type */
enum {
VX_UER_MODE_CONSUMER ,
VX_UER_MODE_PROFESSIONAL ,
VX_UER_MODE_NOT_PRESENT ,
} ;
/* register indices */
enum {
VX_ICR ,
VX_CVR ,
VX_ISR ,
VX_IVR ,
VX_RXH ,
VX_TXH = VX_RXH ,
VX_RXM ,
VX_TXM = VX_RXM ,
VX_RXL ,
VX_TXL = VX_RXL ,
VX_DMA ,
VX_CDSP ,
VX_RFREQ ,
VX_RUER_V2 ,
VX_GAIN ,
VX_DATA = VX_GAIN ,
VX_MEMIRQ ,
VX_ACQ ,
VX_BIT0 ,
VX_BIT1 ,
VX_MIC0 ,
VX_MIC1 ,
VX_MIC2 ,
VX_MIC3 ,
VX_PLX0 ,
VX_PLX1 ,
VX_PLX2 ,
VX_LOFREQ , // V2: ACQ, VP: RFREQ
VX_HIFREQ , // V2: BIT0, VP: RUER_V2
VX_CSUER , // V2: BIT1, VP: BIT0
VX_RUER , // V2: RUER_V2, VP: BIT1
VX_REG_MAX ,
/* aliases for VX board */
VX_RESET_DMA = VX_ISR ,
VX_CFG = VX_RFREQ ,
VX_STATUS = VX_MEMIRQ ,
VX_SELMIC = VX_MIC0 ,
VX_COMPOT = VX_MIC1 ,
VX_SCOMPR = VX_MIC2 ,
VX_GLIMIT = VX_MIC3 ,
VX_INTCSR = VX_PLX0 ,
VX_CNTRL = VX_PLX1 ,
VX_GPIOC = VX_PLX2 ,
/* aliases for VXPOCKET board */
VX_MICRO = VX_MEMIRQ ,
VX_CODEC2 = VX_MEMIRQ ,
VX_DIALOG = VX_ACQ ,
} ;
/* RMH status type */
enum {
RMH_SSIZE_FIXED = 0 , /* status size given by the driver (in LgStat) */
RMH_SSIZE_ARG = 1 , /* status size given in the LSB byte */
RMH_SSIZE_MASK = 2 , /* status size given in bitmask */
} ;
/* bits for ICR register */
# define ICR_HF1 0x10
# define ICR_HF0 0x08
# define ICR_TREQ 0x02 /* Interrupt mode + HREQ set on for transfer (->DSP) request */
# define ICR_RREQ 0x01 /* Interrupt mode + RREQ set on for transfer (->PC) request */
/* bits for CVR register */
# define CVR_HC 0x80
/* bits for ISR register */
# define ISR_HF3 0x10
# define ISR_HF2 0x08
# define ISR_CHK 0x10
# define ISR_ERR 0x08
# define ISR_TX_READY 0x04
# define ISR_TX_EMPTY 0x02
# define ISR_RX_FULL 0x01
/* Constants used to access the DATA register */
# define VX_DATA_CODEC_MASK 0x80
# define VX_DATA_XICOR_MASK 0x80
/* Constants used to access the CSUER register (both for VX2 and VXP) */
# define VX_SUER_FREQ_MASK 0x0c
# define VX_SUER_FREQ_32KHz_MASK 0x0c
# define VX_SUER_FREQ_44KHz_MASK 0x00
# define VX_SUER_FREQ_48KHz_MASK 0x04
# define VX_SUER_DATA_PRESENT_MASK 0x02
# define VX_SUER_CLOCK_PRESENT_MASK 0x01
# define VX_CUER_HH_BITC_SEL_MASK 0x08
# define VX_CUER_MH_BITC_SEL_MASK 0x04
# define VX_CUER_ML_BITC_SEL_MASK 0x02
# define VX_CUER_LL_BITC_SEL_MASK 0x01
# define XX_UER_CBITS_OFFSET_MASK 0x1f
/* bits for audio_info */
# define VX_AUDIO_INFO_REAL_TIME (1<<0) /* real-time processing available */
# define VX_AUDIO_INFO_OFFLINE (1<<1) /* offline processing available */
# define VX_AUDIO_INFO_MPEG1 (1<<5)
# define VX_AUDIO_INFO_MPEG2 (1<<6)
# define VX_AUDIO_INFO_LINEAR_8 (1<<7)
# define VX_AUDIO_INFO_LINEAR_16 (1<<8)
# define VX_AUDIO_INFO_LINEAR_24 (1<<9)
/* DSP Interrupt Request values */
# define VXP_IRQ_OFFSET 0x40 /* add 0x40 offset for vxpocket and vx222/v2 */
/* call with vx_send_irq_dsp() */
# define IRQ_MESS_WRITE_END 0x30
# define IRQ_MESS_WRITE_NEXT 0x32
# define IRQ_MESS_READ_NEXT 0x34
# define IRQ_MESS_READ_END 0x36
# define IRQ_MESSAGE 0x38
# define IRQ_RESET_CHK 0x3A
# define IRQ_CONNECT_STREAM_NEXT 0x26
# define IRQ_CONNECT_STREAM_END 0x28
# define IRQ_PAUSE_START_CONNECT 0x2A
# define IRQ_END_CONNECTION 0x2C
/* Is there async. events pending ( IT Source Test ) */
# define ASYNC_EVENTS_PENDING 0x008000
# define HBUFFER_EVENTS_PENDING 0x004000 // Not always accurate
# define NOTIF_EVENTS_PENDING 0x002000
# define TIME_CODE_EVENT_PENDING 0x001000
# define FREQUENCY_CHANGE_EVENT_PENDING 0x000800
# define END_OF_BUFFER_EVENTS_PENDING 0x000400
# define FATAL_DSP_ERROR 0xff0000
/* Stream Format Header Defines */
# define HEADER_FMT_BASE 0xFED00000
# define HEADER_FMT_MONO 0x000000C0
# define HEADER_FMT_INTEL 0x00008000
# define HEADER_FMT_16BITS 0x00002000
# define HEADER_FMT_24BITS 0x00004000
# define HEADER_FMT_UPTO11 0x00000200 /* frequency is less or equ. to 11k.*/
# define HEADER_FMT_UPTO32 0x00000100 /* frequency is over 11k and less then 32k.*/
/* Constants used to access the Codec */
# define XX_CODEC_SELECTOR 0x20
/* codec commands */
# define XX_CODEC_ADC_CONTROL_REGISTER 0x01
# define XX_CODEC_DAC_CONTROL_REGISTER 0x02
# define XX_CODEC_LEVEL_LEFT_REGISTER 0x03
# define XX_CODEC_LEVEL_RIGHT_REGISTER 0x04
# define XX_CODEC_PORT_MODE_REGISTER 0x05
# define XX_CODEC_STATUS_REPORT_REGISTER 0x06
# define XX_CODEC_CLOCK_CONTROL_REGISTER 0x07
/*
* Audio - level control values
*/
# define CVAL_M110DB 0x000 /* -110dB */
# define CVAL_M99DB 0x02C
# define CVAL_M21DB 0x163
# define CVAL_M18DB 0x16F
# define CVAL_M10DB 0x18F
# define CVAL_0DB 0x1B7
# define CVAL_18DB 0x1FF /* +18dB */
# define CVAL_MAX 0x1FF
# define AUDIO_IO_HAS_MUTE_LEVEL 0x400000
# define AUDIO_IO_HAS_MUTE_MONITORING_1 0x200000
# define AUDIO_IO_HAS_MUTE_MONITORING_2 0x100000
# define VALID_AUDIO_IO_DIGITAL_LEVEL 0x01
# define VALID_AUDIO_IO_MONITORING_LEVEL 0x02
# define VALID_AUDIO_IO_MUTE_LEVEL 0x04
# define VALID_AUDIO_IO_MUTE_MONITORING_1 0x08
# define VALID_AUDIO_IO_MUTE_MONITORING_2 0x10
# endif /* __SOUND_VX_COMMON_H */