|
|
|
|
#ifndef _NM256_H_
|
|
|
|
|
#define _NM256_H_
|
|
|
|
|
|
|
|
|
|
#include <linux/spinlock.h>
|
|
|
|
|
#include <linux/interrupt.h>
|
|
|
|
|
|
|
|
|
|
#include "ac97.h"
|
|
|
|
|
|
|
|
|
|
/* The revisions that we currently handle. */
|
|
|
|
|
enum nm256rev {
|
|
|
|
|
REV_NM256AV, REV_NM256ZX
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Per-card structure. */
|
|
|
|
|
struct nm256_info
|
|
|
|
|
{
|
|
|
|
|
/* Magic number used to verify that this struct is valid. */
|
|
|
|
|
#define NM_MAGIC_SIG 0x55aa00ff
|
|
|
|
|
int magsig;
|
|
|
|
|
|
|
|
|
|
/* Revision number */
|
|
|
|
|
enum nm256rev rev;
|
|
|
|
|
|
|
|
|
|
struct ac97_hwint mdev;
|
|
|
|
|
|
|
|
|
|
/* Our audio device numbers. */
|
|
|
|
|
int dev[2];
|
|
|
|
|
|
|
|
|
|
/* The # of times each device has been opened. (Should only be
|
|
|
|
|
0 or 1). */
|
|
|
|
|
int opencnt[2];
|
|
|
|
|
|
|
|
|
|
/* We use two devices, because we can do simultaneous play and record.
|
|
|
|
|
This keeps track of which device is being used for what purpose;
|
|
|
|
|
these are the actual device numbers. */
|
|
|
|
|
int dev_for_play;
|
|
|
|
|
int dev_for_record;
|
|
|
|
|
|
|
|
|
|
spinlock_t lock;
|
|
|
|
|
|
|
|
|
|
/* The mixer device. */
|
|
|
|
|
int mixer_oss_dev;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Can only be opened once for each operation. These aren't set
|
|
|
|
|
* until an actual I/O operation is performed; this allows one
|
|
|
|
|
* device to be open for read/write without inhibiting I/O to
|
|
|
|
|
* the other device.
|
|
|
|
|
*/
|
|
|
|
|
int is_open_play;
|
|
|
|
|
int is_open_record;
|
|
|
|
|
|
|
|
|
|
/* Non-zero if we're currently playing a sample. */
|
|
|
|
|
int playing;
|
|
|
|
|
/* Ditto for recording a sample. */
|
|
|
|
|
int recording;
|
|
|
|
|
|
|
|
|
|
/* The two memory ports. */
|
|
|
|
|
struct nm256_ports {
|
|
|
|
|
/* Physical address of the port. */
|
|
|
|
|
u32 physaddr;
|
|
|
|
|
/* Our mapped-in pointer. */
|
|
|
|
|
char __iomem *ptr;
|
|
|
|
|
/* PTR's offset within the physical port. */
|
|
|
|
|
u32 start_offset;
|
|
|
|
|
/* And the offset of the end of the buffer. */
|
|
|
|
|
u32 end_offset;
|
|
|
|
|
} port[2];
|
|
|
|
|
|
|
|
|
|
/* The following are offsets within memory port 1. */
|
|
|
|
|
u32 coeffBuf;
|
|
|
|
|
u32 allCoeffBuf;
|
|
|
|
|
|
|
|
|
|
/* Record and playback buffers. */
|
|
|
|
|
u32 abuf1, abuf2;
|
|
|
|
|
|
|
|
|
|
/* Offset of the AC97 mixer in memory port 2. */
|
|
|
|
|
u32 mixer;
|
|
|
|
|
|
|
|
|
|
/* Offset of the mixer status register in memory port 2. */
|
|
|
|
|
u32 mixer_status_offset;
|
|
|
|
|
|
|
|
|
|
/* Non-zero if we have written initial values to the mixer. */
|
|
|
|
|
u8 mixer_values_init;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Status mask bit; (*mixer_status_loc & mixer_status_mask) == 0 means
|
|
|
|
|
* it's ready.
|
|
|
|
|
*/
|
|
|
|
|
u16 mixer_status_mask;
|
|
|
|
|
|
|
|
|
|
/* The sizes of the playback and record ring buffers. */
|
|
|
|
|
u32 playbackBufferSize;
|
|
|
|
|
u32 recordBufferSize;
|
|
|
|
|
|
|
|
|
|
/* Are the coefficient values in the memory cache current? */
|
|
|
|
|
u8 coeffsCurrent;
|
|
|
|
|
|
|
|
|
|
/* For writes, the amount we last wrote. */
|
|
|
|
|
u32 requested_amt;
|
|
|
|
|
/* The start of the block currently playing. */
|
|
|
|
|
u32 curPlayPos;
|
|
|
|
|
|
|
|
|
|
/* The amount of data we were requested to record. */
|
|
|
|
|
u32 requestedRecAmt;
|
|
|
|
|
/* The offset of the currently-recording block. */
|
|
|
|
|
u32 curRecPos;
|
|
|
|
|
/* The destination buffer. */
|
|
|
|
|
char *recBuf;
|
|
|
|
|
|
|
|
|
|
/* Our IRQ number. */
|
|
|
|
|
int irq;
|
|
|
|
|
|
|
|
|
|
/* A flag indicating how many times we've grabbed the IRQ. */
|
|
|
|
|
int has_irq;
|
|
|
|
|
|
|
|
|
|
/* The card interrupt service routine. */
|
|
|
|
|
irqreturn_t (*introutine) (int, void *, struct pt_regs *);
|
|
|
|
|
|
|
|
|
|
/* Current audio config, cached. */
|
|
|
|
|
struct sinfo {
|
|
|
|
|
u32 samplerate;
|
|
|
|
|
u8 bits;
|
|
|
|
|
u8 stereo;
|
|
|
|
|
} sinfo[2]; /* goes with each device */
|
|
|
|
|
|
|
|
|
|
/* The cards are stored in a chain; this is the next card. */
|
|
|
|
|
struct nm256_info *next_card;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Debug flag--bigger numbers mean more output. */
|
|
|
|
|
extern int nm256_debug;
|
|
|
|
|
|
|
|
|
|
/* The BIOS signature. */
|
|
|
|
|
#define NM_SIGNATURE 0x4e4d0000
|
|
|
|
|
/* Signature mask. */
|
|
|
|
|
#define NM_SIG_MASK 0xffff0000
|
|
|
|
|
|
|
|
|
|
/* Size of the second memory area. */
|
|
|
|
|
#define NM_PORT2_SIZE 4096
|
|
|
|
|
|
|
|
|
|
/* The base offset of the mixer in the second memory area. */
|
|
|
|
|
#define NM_MIXER_OFFSET 0x600
|
|
|
|
|
|
|
|
|
|
/* The maximum size of a coefficient entry. */
|
|
|
|
|
#define NM_MAX_COEFFICIENT 0x5000
|
|
|
|
|
|
|
|
|
|
/* The interrupt register. */
|
|
|
|
|
#define NM_INT_REG 0xa04
|
|
|
|
|
/* And its bits. */
|
|
|
|
|
#define NM_PLAYBACK_INT 0x40
|
|
|
|
|
#define NM_RECORD_INT 0x100
|
|
|
|
|
#define NM_MISC_INT_1 0x4000
|
|
|
|
|
#define NM_MISC_INT_2 0x1
|
|
|
|
|
#define NM_ACK_INT(CARD, X) nm256_writePort16((CARD), 2, NM_INT_REG, (X) << 1)
|
|
|
|
|
|
|
|
|
|
/* The AV's "mixer ready" status bit and location. */
|
|
|
|
|
#define NM_MIXER_STATUS_OFFSET 0xa04
|
|
|
|
|
#define NM_MIXER_READY_MASK 0x0800
|
|
|
|
|
#define NM_MIXER_PRESENCE 0xa06
|
|
|
|
|
#define NM_PRESENCE_MASK 0x0050
|
|
|
|
|
#define NM_PRESENCE_VALUE 0x0040
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* For the ZX. It uses the same interrupt register, but it holds 32
|
|
|
|
|
* bits instead of 16.
|
|
|
|
|
*/
|
|
|
|
|
#define NM2_PLAYBACK_INT 0x10000
|
|
|
|
|
#define NM2_RECORD_INT 0x80000
|
|
|
|
|
#define NM2_MISC_INT_1 0x8
|
|
|
|
|
#define NM2_MISC_INT_2 0x2
|
|
|
|
|
#define NM2_ACK_INT(CARD, X) nm256_writePort32((CARD), 2, NM_INT_REG, (X))
|
|
|
|
|
|
|
|
|
|
/* The ZX's "mixer ready" status bit and location. */
|
|
|
|
|
#define NM2_MIXER_STATUS_OFFSET 0xa06
|
|
|
|
|
#define NM2_MIXER_READY_MASK 0x0800
|
|
|
|
|
|
|
|
|
|
/* The playback registers start from here. */
|
|
|
|
|
#define NM_PLAYBACK_REG_OFFSET 0x0
|
|
|
|
|
/* The record registers start from here. */
|
|
|
|
|
#define NM_RECORD_REG_OFFSET 0x200
|
|
|
|
|
|
|
|
|
|
/* The rate register is located 2 bytes from the start of the register area. */
|
|
|
|
|
#define NM_RATE_REG_OFFSET 2
|
|
|
|
|
|
|
|
|
|
/* Mono/stereo flag, number of bits on playback, and rate mask. */
|
|
|
|
|
#define NM_RATE_STEREO 1
|
|
|
|
|
#define NM_RATE_BITS_16 2
|
|
|
|
|
#define NM_RATE_MASK 0xf0
|
|
|
|
|
|
|
|
|
|
/* Playback enable register. */
|
|
|
|
|
#define NM_PLAYBACK_ENABLE_REG (NM_PLAYBACK_REG_OFFSET + 0x1)
|
|
|
|
|
#define NM_PLAYBACK_ENABLE_FLAG 1
|
|
|
|
|
#define NM_PLAYBACK_ONESHOT 2
|
|
|
|
|
#define NM_PLAYBACK_FREERUN 4
|
|
|
|
|
|
|
|
|
|
/* Mutes the audio output. */
|
|
|
|
|
#define NM_AUDIO_MUTE_REG (NM_PLAYBACK_REG_OFFSET + 0x18)
|
|
|
|
|
#define NM_AUDIO_MUTE_LEFT 0x8000
|
|
|
|
|
#define NM_AUDIO_MUTE_RIGHT 0x0080
|
|
|
|
|
|
|
|
|
|
/* Recording enable register. */
|
|
|
|
|
#define NM_RECORD_ENABLE_REG (NM_RECORD_REG_OFFSET + 0)
|
|
|
|
|
#define NM_RECORD_ENABLE_FLAG 1
|
|
|
|
|
#define NM_RECORD_FREERUN 2
|
|
|
|
|
|
|
|
|
|
#define NM_RBUFFER_START (NM_RECORD_REG_OFFSET + 0x4)
|
|
|
|
|
#define NM_RBUFFER_END (NM_RECORD_REG_OFFSET + 0x10)
|
|
|
|
|
#define NM_RBUFFER_WMARK (NM_RECORD_REG_OFFSET + 0xc)
|
|
|
|
|
#define NM_RBUFFER_CURRP (NM_RECORD_REG_OFFSET + 0x8)
|
|
|
|
|
|
|
|
|
|
#define NM_PBUFFER_START (NM_PLAYBACK_REG_OFFSET + 0x4)
|
|
|
|
|
#define NM_PBUFFER_END (NM_PLAYBACK_REG_OFFSET + 0x14)
|
|
|
|
|
#define NM_PBUFFER_WMARK (NM_PLAYBACK_REG_OFFSET + 0xc)
|
|
|
|
|
#define NM_PBUFFER_CURRP (NM_PLAYBACK_REG_OFFSET + 0x8)
|
|
|
|
|
|
|
|
|
|
/* A few trivial routines to make it easier to work with the registers
|
|
|
|
|
on the chip. */
|
|
|
|
|
|
|
|
|
|
/* This is a common code portion used to fix up the port offsets. */
|
|
|
|
|
#define NM_FIX_PORT \
|
|
|
|
|
if (port < 1 || port > 2 || card == NULL) \
|
|
|
|
|
return -1; \
|
|
|
|
|
\
|
|
|
|
|
if (offset < card->port[port - 1].start_offset \
|
|
|
|
|
|| offset >= card->port[port - 1].end_offset) { \
|
|
|
|
|
printk (KERN_ERR "Bad access: port %d, offset 0x%x\n", port, offset); \
|
|
|
|
|
return -1; \
|
|
|
|
|
} \
|
|
|
|
|
offset -= card->port[port - 1].start_offset;
|
|
|
|
|
|
|
|
|
|
#define DEFwritePortX(X, func) \
|
|
|
|
|
static inline int nm256_writePort##X (struct nm256_info *card,\
|
|
|
|
|
int port, int offset, int value)\
|
|
|
|
|
{\
|
|
|
|
|
u##X __iomem *addr;\
|
|
|
|
|
\
|
|
|
|
|
if (nm256_debug > 1)\
|
|
|
|
|
printk (KERN_DEBUG "Writing 0x%x to %d:0x%x\n", value, port, offset);\
|
|
|
|
|
\
|
|
|
|
|
NM_FIX_PORT;\
|
|
|
|
|
\
|
|
|
|
|
addr = (u##X __iomem *)(card->port[port - 1].ptr + offset);\
|
|
|
|
|
func (value, addr);\
|
|
|
|
|
return 0;\
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEFwritePortX (8, writeb)
|
|
|
|
|
DEFwritePortX (16, writew)
|
|
|
|
|
DEFwritePortX (32, writel)
|
|
|
|
|
|
|
|
|
|
#define DEFreadPortX(X, func) \
|
|
|
|
|
static inline u##X nm256_readPort##X (struct nm256_info *card,\
|
|
|
|
|
int port, int offset)\
|
|
|
|
|
{\
|
|
|
|
|
u##X __iomem *addr;\
|
|
|
|
|
\
|
|
|
|
|
NM_FIX_PORT\
|
|
|
|
|
\
|
|
|
|
|
addr = (u##X __iomem *)(card->port[port - 1].ptr + offset);\
|
|
|
|
|
return func(addr);\
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEFreadPortX (8, readb)
|
|
|
|
|
DEFreadPortX (16, readw)
|
|
|
|
|
DEFreadPortX (32, readl)
|
|
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
|
nm256_writeBuffer8 (struct nm256_info *card, u8 *src, int port, int offset,
|
|
|
|
|
int amt)
|
|
|
|
|
{
|
|
|
|
|
NM_FIX_PORT;
|
|
|
|
|
memcpy_toio (card->port[port - 1].ptr + offset, src, amt);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
|
nm256_readBuffer8 (struct nm256_info *card, u8 *dst, int port, int offset,
|
|
|
|
|
int amt)
|
|
|
|
|
{
|
|
|
|
|
NM_FIX_PORT;
|
|
|
|
|
memcpy_fromio (dst, card->port[port - 1].ptr + offset, amt);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns a non-zero value if we should use the coefficient cache. */
|
|
|
|
|
extern int nm256_cachedCoefficients (struct nm256_info *card);
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Local variables:
|
|
|
|
|
* c-basic-offset: 4
|
|
|
|
|
* End:
|
|
|
|
|
*/
|