audioemu10k.h revision 992413f4053d9470046876b234fe094062b730b7
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Purpose: Definitions for the SB Live/Audigy driver
*/
/*
* Copyright (C) 4Front Technologies 1996-2009.
*/
#ifndef EMU10K_H
#define EMU10K_H
#define PCI_VENDOR_ID_CREATIVE 0x1102
#define PCI_DEVICE_ID_SBLIVE 0x0002
#define PCI_DEVICE_ID_AUDIGY 0x0004
#define PCI_DEVICE_ID_AUDIGYVALUE 0x0008
#define SAMPLE_RATE 48000
#define EMU10K_NAME "audioemu10k"
#define EMU10K_NUM_PORTC 2
#define EMU10K_PLAY 0
#define EMU10K_REC 1
#define EMU10K_NUM_FRAGS (2*4) /* Must be multiple of 2 */
#define EMU10K_MAX_INTRS 512
#define EMU10K_MIN_INTRS 10
#define EMU10K_INTRS 100
#define FRAGMENT_FRAMES 512
#define EMU10K1_MAGIC 0xe10001
#define EMU10K2_MAGIC 0xe10002
/* Audio */
#define DMABUF_SIZE (256 * 1024)
#define AUDIO_MAXVOICE (2*EMU10K_NUM_PORTC)
/* Audio buffer + silent page */
#define AUDIO_MEMSIZE (EMU10K_NUM_PORTC*DMABUF_SIZE+4096)
/* Wall clock register */
#define WC 0x10
/* Hardware config register */
#define HCFG 0x14
#define HCFG_CODECFORMAT_MASK 0x00070000 /* CODEC format */
#define HCFG_CODECFORMAT_AC97 0x00000000 /* AC97 CODEC format */
#define HCFG_CODECFORMAT_I2S 0x00010000 /* I2S CODEC format */
#define HCFG_GPINPUT0 0x00004000 /* External pin112 */
#define HCFG_GPINPUT1 0x00002000 /* External pin110 */
#define HCFG_GPOUTPUT_MASK 0x00001c00 /* Controllable pins */
#define HCFG_GPOUT0 0x00001000 /* enable dig out on 5.1 */
#define HCFG_GPOUT1 0x00000800 /* IR */
#define HCFG_GPOUT2 0x00000400 /* IR */
#define HCFG_JOYENABLE 0x00000200 /* Internal joystick enable */
#define HCFG_PHASETRACKENABLE 0x00000100 /* Phase tracking enable */
#define HCFG_AC3ENABLE_MASK 0x0x0000e0 /* AC3 async input control */
#define HCFG_AC3ENABLE_ZVIDEO 0x00000080 /* Chan 0/1 replace ZVIDEO */
#define HCFG_AC3ENABLE_CDSPDIF 0x00000040 /* Chan 0/1 replace CDSPDIF */
#define HCFG_AC3ENABLE_GPSPDIF 0x00000020 /* Chan 0/1 replace GPSPDIF */
#define HCFG_AUTOMUTE 0x00000010
#define HCFG_LOCKSOUNDCACHE 0x00000008
#define HCFG_LOCKTANKCACHE_MASK 0x00000004
#define HCFG_LOCKTANKCACHE 0x01020014
#define HCFG_MUTEBUTTONENABLE 0x00000002 /* Mute can clear audioenable */
#define HCFG_AUDIOENABLE 0x00000001 /* Codecs can send data */
#define A_HCFG_VMUTE 0x00004000
#define A_HCFG_AUTOMUTE 0x00008000
#define A_HCFG_XM 0x00040000 /* Xtended address mode */
/*
* GPIO bit definitions (global register 0x18) for Audigy.
*/
#define A_IOCFG_GPOUT0 0x0044 /* analog/digital? */
#define A_IOCFG_GPOUT1 0x0002 /* IR */
#define A_IOCFG_GPOUT2 0x0001 /* IR */
/* Status bits (read only) */
#define GPIO_VERSAPLUGGED 0x2000 /* Center/LFE/digital */
#define GPIO_FRONTPLUGGED 0x4000
#define GPIO_REARPLUGGED 0x8000
#define GPIO_HEADPHPLUGGED 0x0100
#define GPIO_ANALOG_MUTE 0x0040
#define GPIO_DIGITAL_ENABLE 0x0004 /* Cen/lfe (0) or digital (1) switch */
#define FILL_PAGE_MAP_ENTRY(e, v) \
ddi_put32(devc->pt_acch, devc->page_map + e, ((v) << 1) | (e));
/*
* Audio block registers
*/
#define CPF 0x000 /* DW:cnl Current pitch and fraction */
#define CPF_CURRENTPITCH_MASK 0xffff0000
#define CPF_CURRENTPITCH 0x10100000
#define CPF_STEREO_MASK 0x00008000
#define CPF_STOP_MASK 0x00004000
#define CPF_FRACADDRESS_MASK 0x00003fff
#define PTAB 0x001 /* DW:cnl Pitch target and sends A and B */
#define PTRX_PITCHTARGET_MASK 0xffff0000
#define PTRX_PITCHTARGET 0x10100001
#define PTRX_FXSENDAMOUNT_A_MASK 0x0000ff00
#define PTRX_FXSENDAMOUNT_A 0x08080001
#define PTRX_FXSENDAMOUNT_B_MASK 0x000000ff
#define PTRX_FXSENDAMOUNT_B 0x08000001
#define CVCF 0x002 /* DW:cnl Curr vol and curr filter cutoff */
#define VTFT 0x003 /* DW:cnl Volume tgt and filter cutoff tgt */
#define Z2 0x004 /* DW:cnl Filter delay memory 2 */
#define Z1 0x005 /* DW:cnl Filter delay memory 1 */
#define SCSA 0x006 /* DW:cnl Send C and Start addr */
#define SDL 0x007 /* DW:cnl Send D and Loop addr */
#define QKBCA 0x008 /* DW:cnl Filter Q, ROM, etc */
#define CCR 0x009
#define CCR_CACHEINVALIDSIZE 0x07190009
#define CCR_CACHEINVALIDSIZE_MASK 0xfe000000
#define CCR_CACHELOOPFLAG 0x01000000
#define CCR_INTERLEAVEDSAMPLES 0x00800000
#define CCR_WORDSIZEDSAMPLES 0x00400000
#define CCR_READADDRESS 0x06100009
#define CCR_READADDRESS_MASK 0x003f0000
#define CCR_LOOPINVALSIZE 0x0000fe00
#define CCR_LOOPFLAG 0x00000100
#define CCR_CACHELOOPADDRHI 0x000000ff
#define CLP 0x00a
#define SRHE 0x07c
#define STHE 0x07d
#define SRDA 0x07e
#define STDA 0x07f
#define L_FXRT 0x00b
#define FXRT 0x00b /* W:cnl */
#define MAPA 0x00c
#define MAPB 0x00d
#define VEV 0x010 /* W:cnl */
#define VEHA 0x011 /* W:cnl */
#define VEDS 0x012 /* W:cnl */
#define MLV 0x013 /* W:cnl */
#define MEV 0x014 /* W:cnl */
#define MEHA 0x015 /* W:cnl */
#define MEDS 0x016 /* W:cnl */
#define VLV 0x017 /* W:cnl */
#define IP 0x018 /* W:cnl */
#define IFA 0x019 /* W:cnl */
#define PEFE 0x01a /* W:cnl */
#define PEFE_PITCHAMOUNT_MASK 0x0000ff00 /* Pitch envlope amount */
#define PEFE_PITCHAMOUNT 0x0808001a
#define PEFE_FILTERAMOUNT_MASK 0x000000ff /* Filter envlope amount */
#define PEFE_FILTERAMOUNT 0x0800001a
#define VFM 0x01b /* W:cnl */
#define TMFQ 0x01c /* W:cnl */
#define VVFQ 0x01d /* W:cnl */
#define TMPE 0x01e /* W:cnl */
#define CD0 0x020 /* DW:cnl (16 registers) */
#define PTBA 0x040 /* DW:nocnl */
#define TCBA 0x041 /* DW:nocnl */
#define ADCSR 0x042 /* B:nocnl */
#define FXWC 0x043 /* DW:nocnl */
#define TCBS 0x044 /* B:nocnl */
#define MBA 0x045 /* DW:nocnl */
#define ADCBA 0x046 /* DW:nocnl */
#define FXBA 0x047 /* DW:nocnl */
#define MBS 0x049 /* B:nocnl */
#define ADCBS 0x04a /* B:nocnl */
#define FXBS 0x04b /* B:nocnl */
#define CSBA 0x4c
#define CSDC 0x4d
#define CSFE 0x4e
#define CSHG 0x4f
#define CDCS 0x050 /* DW:nocnl */
#define GPSCS 0x051 /* DW:nocnl */
#define DBG 0x052 /* DW:nocnl */
#define AUDIGY_DBG 0x053 /* DW:nocnl */
#define SCS0 0x054 /* DW:nocnl */
#define SCS1 0x055 /* DW:nocnl */
#define SCS2 0x056 /* DW:nocnl */
#define CLIEL 0x058 /* DW:nocnl */
#define CLIEH 0x059 /* DW:nocnl */
#define CLIPL 0x05a /* DW:nocnl */
#define CLIPH 0x05b /* DW:nocnl */
#define SOLL 0x05c /* DW:nocnl */
#define SOLH 0x05d /* DW:nocnl */
#define SOC 0x05e /* DW:nocnl */
#define AC97SLOT 0x05f
#define AC97SLOT_REAR_RIGHT 0x01
#define AC97SLOT_REAR_LEFT 0x02
#define AC97SLOT_CENTER 0x10
#define AC97SLOT_LFE 0x20
#define CDSRCS 0x060 /* DW:nocnl */
#define GPSRCS 0x061 /* DW:nocnl */
#define ZVSRCS 0x062 /* DW:nocnl */
#define ADCIDX 0x063 /* W:nocnl */
#define MIDX 0x064 /* W:nocnl */
#define FXIDX 0x065 /* W:nocnl */
/* Half loop interrupt registers (audigy only) */
#define HLIEL 0x066 /* DW:nocnl */
#define HLIEH 0x067 /* DW:nocnl */
#define HLIPL 0x068 /* DW:nocnl */
#define HLIPH 0x069 /* DW:nocnl */
#define GPR0 ((devc->feature_mask&SB_LIVE)? 0x100:0x400) /* DW:nocnl */
#define TMA0 0x300 /* Tank memory */
#define UC0 ((devc->feature_mask&SB_LIVE) ? 0x400:0x600) /* DSM ucode */
/* Interrupt pending register */
#define INTPEND 0x08
#define INT_VI 0x00100000
#define INT_VD 0x00080000
#define INT_MU 0x00040000
#define INT_MF 0x00020000
#define INT_MH 0x00010000
#define INT_AF 0x00008000
#define INT_AH 0x00004000
#define INT_IT 0x00000200
#define INT_TX 0x00000100
#define INT_RX 0x00000080
#define INT_CL 0x00000040
/* Interrupt enable register */
#define IE 0x0c
#define IE_VI 0x00000400
#define IE_VD 0x00000200
#define IE_MU 0x00000100
#define IE_MB 0x00000080
#define IE_AB 0x00000040
#define IE_IT 0x00000004
#define IE_TX 0x00000002
#define IE_RX 0x00000001
/* Interval timer register */
#define TIMR 0x1a
/* EMU10K2 MIDI UART */
#define MUADAT 0x070
#define MUACMD 0x071
#define MUASTAT MUACMD
/* EMU10K2 S/PDIF recording buffer */
#define SPRI 0x6a
#define SPRA 0x6b
#define SPRC 0x6c
#define EHC 0x76 /* Audigy 2 */
#define SRHE 0x07c
#define STHE 0x07d
#define SRDA 0x07e
#define ROM0 0x00000000 /* interpolation ROM 0 */
#define ROM1 0x02000000 /* interpolation ROM 1 */
#define ROM2 0x04000000 /* interpolation ROM 2 */
#define ROM3 0x06000000 /* interpolation ROM 3 */
#define ROM4 0x08000000 /* interpolation ROM 4 */
#define ROM5 0x0A000000 /* interpolation ROM 5 */
#define ROM6 0x0C000000 /* interpolation ROM 6 */
#define ROM7 0x0E000000 /* interpolation ROM 7 */
#define BYTESIZE 0x01000000 /* byte sound memory */
#define MAX_GPR 256
/* See feature_mask below */
#define SB_LIVE 1
#define SB_AUDIGY 2
#define SB_AUDIGY2 4
#define SB_AUDIGY2VAL 8
#define SB_51 0x10
#define SB_71 0x20
#define SB_INVSP 0x40 /* invert shared spdif switch */
#define SB_NOEXP 0x80 /* no support for Live! Drive or expansion */
#define LEFT_CH 0
#define RIGHT_CH 1
#ifdef _KERNEL
typedef struct _emu10k_devc_t emu10k_devc_t;
typedef struct _emu10k_portc_t emu10k_portc_t;
typedef enum {
CTL_VOLUME = 0,
CTL_FRONT,
CTL_SURROUND,
CTL_CENTER,
CTL_LFE,
CTL_SIDE,
CTL_HEADPH,
CTL_RECGAIN,
CTL_RECSRC,
CTL_AC97SRC,
/* monitor source values */
CTL_AC97,
CTL_DIGCD,
CTL_SPD1,
CTL_SPD2,
CTL_LINE2,
CTL_AUX2,
CTL_JACK3,
/* this one must be last */
CTL_MAX,
} emu10k_ctrl_id_t;
typedef struct _emu10k_ctrl {
emu10k_devc_t *devc;
audio_ctrl_t *ctrl;
int gpr_num;
uint64_t val;
} emu10k_ctrl_t;
typedef struct _emu10k_gpr {
boolean_t valid;
uint32_t value;
} emu10k_gpr_t;
struct _emu10k_portc_t {
emu10k_devc_t *devc;
audio_engine_t *engine;
/* Helper functions */
void (*update_port)(emu10k_portc_t *);
void (*reset_port)(emu10k_portc_t *);
void (*stop_port)(emu10k_portc_t *);
void (*start_port)(emu10k_portc_t *);
int channels;
boolean_t started;
boolean_t active;
unsigned fragfr;
unsigned nframes;
unsigned nfrags;
unsigned fragsz;
ddi_dma_handle_t buf_dmah; /* dma for buffers */
ddi_acc_handle_t buf_acch;
uint32_t buf_paddr;
caddr_t buf_kaddr;
size_t buf_size;
/* Start of loop within the internal memory space */
uint32_t memptr;
int syncdir;
/* Position & timing */
uint64_t count;
uint32_t pos;
int dopos;
};
struct _emu10k_devc_t {
dev_info_t *dip;
audio_dev_t *adev;
kstat_t *ksp;
boolean_t suspended;
ddi_acc_handle_t pcih;
ddi_acc_handle_t regsh;
caddr_t regs;
kmutex_t mutex;
ddi_intr_handle_t ih;
/*
* Page table
*/
ddi_dma_handle_t pt_dmah; /* dma for page_tablefers */
ddi_acc_handle_t pt_acch;
uint32_t pt_paddr;
caddr_t pt_kaddr;
uint32_t *page_map; /* up to 8k ptrs to 4k pages */
/*
* Silent page used by voices that don't play anything.
*/
ddi_dma_handle_t silence_dmah; /* dma for silencefers */
ddi_acc_handle_t silence_acch;
uint32_t silence_paddr;
caddr_t silence_kaddr;
/*
* Device feature mask tells which kind of features are
* supported by the hardware. Audigy2/2val have multiple bits
* set while Live! has just the SB_LIVE bits. So Features of
* Audigy will be reported by Audigy2/val too.
*/
int feature_mask;
int max_mem, max_pages, nr_pages;
/*
* Mixer
*/
ac97_t *ac97;
ac97_ctrl_t *ac97_recsrc;
uint32_t ac97_stereomix;
emu10k_gpr_t gpr_shadow[MAX_GPR];
emu10k_ctrl_t ctrls[CTL_MAX];
/*
* Audio
*/
int audio_memptr;
int *silent_page;
emu10k_portc_t *portc[EMU10K_NUM_PORTC];
};
#define INB(devc, reg) ddi_get8(devc->regsh, (void *)(reg))
#define OUTB(devc, val, reg) ddi_put8(devc->regsh, (void *)(reg), (val))
#define INW(devc, reg) ddi_get16(devc->regsh, (void *)(reg))
#define OUTW(devc, val, reg) ddi_put16(devc->regsh, (void *)(reg), (val))
#define INL(devc, reg) ddi_get32(devc->regsh, (void *)(reg))
#define OUTL(devc, val, reg) ddi_put32(devc->regsh, (void *)(reg), (val))
#define EMU10K_KIOP(X) ((kstat_intr_t *)(X->ksp->ks_data))
#endif /* _KERNEL */
#endif /* EMU10K_H */