/*
 * Purpose: Definitions for the ICH driver
 */
#ifndef _ICH_H_
#define _ICH_H_

/*
 * This file is part of Open Sound System
 *
 * Copyright (C) 4Front Technologies 1996-2007.
 *
 * This software is released under CDDL 1.0 source license for operating systems
 * that have their full source code available under the BSD or CDDL licenses.
 *
 * See the COPYING file included in the main directory of this source
 * distribution. Please contact sales@opensound.com for further info.
 */

/*
 * NOTE! This is not the development version of this file. Please download the
 * sources of the latest Open Sound System version from 
 * http://developer.opensound.com/sources if you plan to make any changes
 * to the software.
 */
#include "ac97.h"

typedef unsigned char U8;
typedef unsigned short U16;
typedef unsigned int U32;

/* Per-card structure. */
struct intelpci_info
{
  /* Magic number used to verify that this struct is valid. */
#define ICH_MAGIC_SIG 0x48919218
  int magsig;

  /* Chip name. */
  char *chip_name;

  /* The mixer devc. */
  ac97_devc ac97devc;

  /* 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;

  /* 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 base I/O registers for the mixer and sound engine, respectively. */
  int ac97baseIO;
  int intel810baseIO;

#define ICH_PCM_OUT_DESC 0
#define ICH_PCM_IN_DESC 1
#define ICH_MIC_DESC 2
  /* Our buffer descriptors.  One is allocated for each device; they are
     all allocated out of the bdlBuffer pool. */
  char *bdlBuffer;
  /* One buffer descriptor for each device. */
  char *bufferDescriptorList[3];
  /* The first available buffer descriptor slot. */
  U8 currBufferDescriptor[3];
  /* How many buffer descriptors are active. */
  U8 activeBufferCount[3];

  /* Points to the requested block, if we need to do a bit conversion. */
  char *recBuffer;
  /* Points to our local record buffer. */
  char *recBufferOurs;
  /* Number of 8-bit samples requested. */
  U16 recAmt;

  /* Our IRQ number. */
  int irq;

  /* AC97 codec type */
  int ac97codec_type;

  /* Current audio config, cached. */
  struct sinfo
  {
    U32 samplerate;
    U8 bits;
    U8 stereo;
    /* Used for rate conversions. */
    char *dbuff;
    int dbuffphys;
  }
  sinfo[2];			/* goes with each device */

  /* OS info struct for OSS */
  oss_device_t *dev;

  /* The cards are stored in a chain;  this is the next card. */
  struct intelpci_info *next_card;

  /* Next card with the same IRQ.  */
  struct intelpci_info *next_irq;
};

/* Buffer descriptor base address registers. 32 bits. */
#define ICH_PCM_IN_BDBAR		0x00
#define ICH_PCM_OUT_BDBAR		0x10
#define ICH_MIC_BDBAR		0x20

#define ICH_MAX_DESCRIPTORS	32

/* Current index value -- indicates which buffer in the set of buffer
   descriptors is active.  8 bits. */
#define ICH_PCM_IN_CIV		0x04
#define ICH_PCM_OUT_CIV		0x14
#define ICH_MIC_CIV		0x24

/* The last valid index register. 8 bits. */
#define ICH_PCM_IN_LVI		0x05
#define ICH_PCM_OUT_LVI		0x15
#define ICH_MIC_LVI		0x25

/* Main status register. 8 bits. */
#define ICH_PCM_IN_SR		0x06
#define ICH_PCM_OUT_SR		0x16
#define ICH_MIC_SR			0x26

/* All SR interrupt bits cleared by writing a 1. */
/* FIFO error -- underrun or overrun. */
#define ICH_SR_FIFOE		(1 << 4)
/* Set after the last sample of a buffer is completed & IOC is set in the
   command byte of the buffer descriptor. */
#define ICH_SR_BCIS		(1 << 3)
/* Last valid buffer completed. */
#define ICH_SR_LVBCI		(1 << 2)
/* Status flag - current buffer equals last.  Cleared by writing to LVI. */
#define ICH_SR_CELV		(1 << 1)
/* DMA controller halted.  Cleared by clearing the halt condition.  */
#define ICH_SR_DCH			(1 << 0)

/* Position within current buffer. 16-bit register. */
#define ICH_PCM_IN_PICB		0x08
#define ICH_PCM_OUT_PICB		0x18
#define ICH_MIC_PICB		0x28

/* Control rgister. 8 bits. */
#define ICH_PCM_IN_CR		0x0b
#define ICH_PCM_OUT_CR		0x1b
#define ICH_MIC_CR			0x2b

/* Setif an interupt should occur if a buffer is completed and IOC is set
   in its descriptor. */
#define ICH_CR_IOCE		(1 << 4)
/* Set if an interrupt should occur on FIFO error. */
#define ICH_CR_FEIE		(1 << 3)
/* Set if completion of the last valid buffer should cause an interrupt. */
#define ICH_CR_LVBIE		(1 << 2)
/* Resets all registers except this one. */
#define ICH_CR_RR			(1 << 1)
/* Run/pause control. */
#define ICH_CR_RUN			(1 << 0)

/* Global control register. 32 bits. */
#define ICH_PCM_IN_GLOB_CNT	0x2c

/* Set if a secondary codec resume should cause an interrupt. */
#define ICH_GLOB_CNT_SR_INT_EN	(1 << 5)
/* Set if a primary codec resume should cause an interrupt. */
#define ICH_GLOB_CNT_PR_INT_EN	(1 << 4)
/* Disable all AC97 outputs. */
#define ICH_GLOB_CNT_ACLINK_OFF	(1 << 3)
/* Warm reset the AC link. */
#define ICH_GLOB_CNT_AC_WARM_RESET (1 << 2)
/* Cold reset the AC link. */
#define ICH_GLOB_CNT_AC_COLD_RESET (1 << 1)
/* Set if a GPI status change should cause an interrupt. */
#define ICH_GLOB_CNT_GPI_INT_EN	(1 << 0)

/* Global status register. 32 bits. */
#define ICH_GLOB_STA		0x30
/* Power-down flag for modem. */
#define ICH_GLOB_STA_MD3		(1 << 17)
/* Power-down flag for audio. */
#define ICH_GLOB_STA_AD3		(1 << 16)
/* 1 if a codedc read resulted in a timeout. Must be cleared by software. */
#define ICH_GLOB_STA_READ_COMPLETE (1 << 15)
/* Secondary resume interrupt occurred.  Cleared by writing a 1. */
#define ICH_GLOB_STA_SR_INT	(1 << 11)
/* Primary resume interrupt occurred.  Cleared by writing a 1. */
#define ICH_GLOB_STA_PR_INT	(1 << 10)
/* Secondary codec ready. */
#define ICH_GLOB_STA_SCR		(1 << 9)
/* Primary codec ready. */
#define ICH_GLOB_STA_PCR		(1 << 8)
/* Mic in channel interrupt occurred. */
#define ICH_GLOB_STA_MIC_INT	(1 << 7)
/* PCM out interrupt occurred. */
#define ICH_GLOB_STA_PCM_OUT_INT	(1 << 6)
/* PCM in interrupt occurred. */
#define ICH_GLOB_STA_PCM_IN_INT	(1 << 5)
/* Modem out interrupt occurred. */
#define ICH_GLOB_STA_MO_INT	(1 << 2)
/* Modem in interrupt occurred. */
#define ICH_GLOB_STA_MI_INT	(1 << 1)
/* GPI status change occurred. */
#define ICH_GLOB_STA_GPI_STAT_CHG  (1 << 0)

#define ICH_CODEC_SEMAPHORE	0x34
#define ICH_CODEC_SEMAPHORE_BIT	0x1

#define BDBAR_POLICY_BUP_SET		0x4000
#define BDBAR_POLICY_IOC_ENABLE		0x8000

#define ICH_GLOB_STA_INT (ICH_GLOB_STA_SR_INT \
			       | ICH_GLOB_STA_PR_INT \
			       | ICH_GLOB_STA_MIC_INT \
			       | ICH_GLOB_STA_PCM_OUT_INT \
			       | ICH_GLOB_STA_PCM_IN_INT \
			       | ICH_GLOB_STA_MO_INT \
			       | ICH_GLOB_STA_MI_INT \
			       | ICH_GLOB_STA_GPI_STAT_CHG)

static int intelpci_isReady (struct intelpci_info *card);

static inline U32
intelpci_read810Reg32 (struct intelpci_info *card, int reg)
{
  return INL (card->osp, card->intel810baseIO + reg);
}

static inline U16
intelpci_read810Reg16 (struct intelpci_info *card, int reg)
{
  return INW (card->osp, card->intel810baseIO + reg);
}

static inline U32
intelpci_read810Reg8 (struct intelpci_info *card, int reg)
{
  return INB (card->osp, card->intel810baseIO + reg);
}


static inline void
intelpci_write810Reg8 (struct intelpci_info *card, int reg, U8 val)
{
  OUTB (card->osp, val, card->intel810baseIO + reg);
}

static inline void
intelpci_write810Reg16 (struct intelpci_info *card, int reg, U16 val)
{
  OUTW (card->osp, val, card->intel810baseIO + reg);
}


static inline void
intelpci_write810Reg32 (struct intelpci_info *card, int reg, U32 val)
{
  OUTL (card->osp, val, card->intel810baseIO + reg);
}

#endif

/*
 * Local variables:
 * c-basic-offset: 4
 * End:
 */
