/*
 *  Copyright (c) 1994/95 by Jaroslav Kysela (Perex soft)
 */

/* IO ports */

#define CODECP( x ) ( codec_port + c_d_c_CODEC##x )

#define c_d_c_CODECREGSEL	0
#define c_d_c_CODECREG		1
#define c_d_c_CODECSTATUS	2
#define c_d_c_CODECPIO		3

/* codec registers */

#define CODEC_LEFT_INPUT	0x00	/* left input control register */
#define CODEC_RIGHT_INPUT	0x01	/* right input control register */
#define CODEC_GF1_LEFT_INPUT	0x02	/* left GF1 input control register */
#define CODEC_GF1_RIGHT_INPUT	0x03	/* right GF1 input control register */
#define CODEC_CD_LEFT_INPUT	0x04	/* left CD input control register */
#define CODEC_CD_RIGHT_INPUT	0x05	/* right CD input control register */
#define CODEC_LEFT_OUTPUT	0x06	/* left output control register */
#define CODEC_RIGHT_OUTPUT	0x07	/* right output control register */
#define CODEC_PLAYBK_FORMAT	0x08	/* clock and data format */
#define CODEC_IFACE_CTRL	0x09	/* interface control */
#define CODEC_PIN_CTRL		0x0a	/* pin control */
#define CODEC_TEST_INIT		0x0b	/* test and initialization */
#define CODEC_MISC_INFO		0x0c	/* miscellaneaous information */
#define CODEC_LOOPBACK		0x0d	/* digital mix */
#define CODEC_PLY_UPR_CNT	0x0e	/* playback upper base count */
#define CODEC_PLY_LWR_CNT	0x0f	/* playback lower base count */
#define CODEC_ALT_FEATURE_1	0x10	/* alternate #1 feature enabled */
#define CODEC_ALT_FEATURE_2	0x11	/* alternate #2 feature enabled */
#define CODEC_LEFT_LINE_IN	0x12	/* left line input control */
#define CODEC_RIGHT_LINE_IN	0x13	/* right line input control */
#define CODEC_TIMER_LOW		0x14	/* timer low byte */
#define CODEC_TIMER_HIGH	0x15	/* timer high byte */
#define CODEC_IRQ_STATUS	0x18	/* irq status register */
#define CODEC_MONO_CTRL		0x1a	/* mono input/output control */
#define CODEC_REC_FORMAT	0x1c	/* record format */
#define CODEC_REC_UPR_CNT	0x1e	/* record upper count */
#define CODEC_REC_LWR_CNT	0x1f	/* record lower count */

/* some redefinitions for me */

#define CODEC_INPUT		CODEC_LEFT_INPUT
#define CODEC_GF1_INPUT		CODEC_GF1_LEFT_INPUT
#define CODEC_CD_INPUT		CODEC_CD_LEFT_INPUT
#define CODEC_OUTPUT		CODEC_LEFT_OUTPUT
#define CODEC_LINE_INPUT	CODEC_LEFT_LINE_IN
#define CODEC_MIC_INPUT		CODEC_MONO_CTRL

/* definitions for codec register select port - CODECP( REGSEL ) */

#define CODEC_INIT		0x80	/* CODEC is initializing */
#define CODEC_MCE		0x40	/* mode change enable */
#define CODEC_TRD		0x20	/* transfer request disable */

/* definitions for codec irq status */

#define CODEC_PLAYBACK_IRQ	0x10
#define CODEC_RECORD_IRQ	0x20
#define CODEC_TIMER_IRQ		0x40

/* definitions for CODEC_LEFT_INPUT and CODEC_RIGHT_INPUT registers */

#define CODEC_ENABLE_MIC_GAIN	0x20

#define CODEC_MIXS_LINE		0x00
#define CODEC_MIXS_GF1		0x40
#define CODEC_MIXS_MIC		0x80
#define CODEC_MIXS_BOTH		0xc0

/* definitions for clock and data format register - CODEC_PLAYBK_FORMAT */

#define CODEC_LINEAR_8		0x00	/* 8-bit unsigned data */
#define CODEC_ALAW_8		0x60	/* 8-bit A-law companded */
#define CODEC_ULAW_8		0x20	/* 8-bit U-law companded */
#define CODEC_LINEAR_16		0x40	/* 16-bit twos complement data - little endian */
#define CODEC_LINEAR_16_BIG	0xc0	/* 16-bit twos complement data - big endian */
#define CODEC_ADPCM_16		0xa0	/* 16-bit ADPCM */
#define CODEC_STEREO		0x10	/* stereo mode */
/* bits 3-1 define frequency divisor */
#define CODEC_XTAL1		0x00	/* 24.576 crystal */
#define CODEC_XTAL2		0x01	/* 16.9344 crystal */

/* definitions for interface control register - CODEC_IFACE_CTRL */

#define CODEC_RECORD_PIO	0x80	/* record PIO enable */
#define CODEC_PLAYBACK_PIO	0x40	/* playback PIO enable */
#define CODEC_AUTOCALIB		0x08	/* auto calibrate */
#define CODEC_SINGLE_DMA	0x04	/* use single DMA channel */
#define CODEC_RECORD_ENABLE	0x02	/* record enable */
#define CODEC_PLAYBACK_ENABLE	0x01	/* playback enable */

/* definitions for pin control register - CODEC_PIN_CTRL */

#define CODEC_IRQ_ENABLE	0x02	/* enable IRQ */
#define CODEC_XCTL1		0x40	/* external control #1 */
#define CODEC_XCTL0		0x80	/* external control #0 */

/* definitions for test and init register - CODEC_TEST_INIT */

#define CODEC_CALIB_IN_PROGRESS 0x20	/* auto calibrate in progress */

/* definitions for misc control register - CODEC_MISC_INFO */

#define CODEC_MODE2		0x40	/* MODE 2 */

/* definitions for alternate feature 1 register - CODEC_ALT_FEATURE_1 */

#define	CODEC_DACZ		0x01	/* zero DAC when underrun */
#define CODEC_TIMER_ENABLE	0x40	/* codec timer enable */
#define CODEC_OLB		0x80	/* output level bit */

/* some structures */

struct codec_freq_stru {
  unsigned int hertz;
  unsigned int rate;
  unsigned char bits;
};

struct codec_image_stru {
  unsigned char lic;
  unsigned char ric;
  unsigned char la1ic;
  unsigned char ra1ic;
  unsigned char la2ic;
  unsigned char ra2ic;
  unsigned char loc;
  unsigned char roc;
  unsigned char pdfr;
  unsigned char ic;
  unsigned char pc;
  unsigned char ti;
  unsigned char mi;
  unsigned char lbc;
  unsigned char pbru;
  unsigned char pbrl;
  unsigned char afei;
  unsigned char afeii;
  unsigned char llic;
  unsigned char rlic;
  unsigned char tlb;
  unsigned char thb;
  unsigned char afs;
  unsigned char mioc;
  unsigned char cdfr;
  unsigned char cbru;
  unsigned char cbrl;
};

/* some inline functions */

extern int codec_port;

extern inline void codec_out( unsigned char reg, unsigned char value )
{
  OUTB( reg, CODECP( REGSEL ) );
  OUTB( value, CODECP( REG ) ); MB();
}
    
extern inline unsigned char codec_in( unsigned char reg )
{
  OUTB( reg, CODECP( REGSEL ) ); MB();
  return INB( CODECP( REG ) );
}

extern inline void codec_wait_reg_sel( unsigned char reg )
{
  OUTB( reg, CODECP( REGSEL ) ); MB();
  while ( INB( CODECP( REGSEL ) ) != reg )
    {
      OUTB( reg, CODECP( REGSEL ) ); 
      MB();
    }
}
