/* 2009-08-20: File added and changed by Sony Corporation */
/*
 * linux/sound/arm/mp200-pcm.h -- ALSA PCM interface for MP200 chip
 *
 * Created: 2009.06.08
 *
 */
/* #define AUDIO_MAKING_DEBUG 1 */

#include <asm/dma.h>
#include <linux/platform_device.h>

#include <sound/mp200_pcm_ioctl.h>

#define MP200_PCM_INTERRUPT_ENABLE 1
#define MP200_PCM_MMAP_ENABLE 1
#if defined(CONFIG_PGPF_PCM_USE_PDMA) || !defined(CONFIG_MACH_PGPF)
#define MP200_PCM_USE_PDMA 1
#define MP200_DAC_HANGUP_PDMA 1
#endif

#ifndef MP200_PCM_USE_PDMA
#undef  MP200_DAC_HANGUP_PDMA
#endif

/* #define MP200_PCM_FMT16     1   */  /* if you want use 32bitPCM(not OMF),
                                   	then comment out this line  */

#define MP200_PCM_CH0		0x00
#define MP200_PCM_CH1		0x01
#define MP200_PCM_MAX_CHANNELS	2

/* func_sel set */
#define MP200_PCM_FUNC_30WORD		0x00000000
#define MP200_PCM_FUNC_16WORD		0x00000020
#define MP200_PCM_FUNC_08WORD		0x00000040
#define MP200_PCM_FUNC_04WORD		0x00000060
#define MP200_PCM_FUNC_MASTER		0x00000008
#define MP200_PCM_FUNC_SLAVE		0x00000010
#define MP200_PCM_FUNC_MODE0		0x00000000
#define MP200_PCM_FUNC_MODE1		0x00000001
#define MP200_PCM_FUNC_MODE2		0x00000002
#define MP200_PCM_FUNC_MODE3		0x00000003
#define MP200_PCM_FUNC_MODE4		0x00000004
#define MP200_PCM_FUNC_MODE5		0x00000005
#define MP200_PCM_FUNC_MODE6		0x00000006

/* cycle set */
#define MP200_PCM_CYCLE_SHT_TX_PD	23
#define MP200_PCM_CYCLE_SHT_SOB		16
#define MP200_PCM_CYCLE_SHT_RX_PD	15
#define MP200_PCM_CYCLE_SHT_SIB		8
#define MP200_PCM_CYCLE_SHT_CYC		0

struct pcm_regs {
	volatile u32 func_sel;	/* +0x00 (r/w) */
	volatile u32 txrx_en;	/* +0x04 (r/w) */
	volatile u32 txrx_dis;	/* +0x08 (w) */
	volatile u32 cycle;	/* +0x0c (r/w) */
	volatile u32 raw;	/* +0x10 (r) */
	volatile u32 status;	/* +0x14 (r) */
	volatile u32 enset;	/* +0x18 (r/w) */
	volatile u32 enclr;	/* +0x1c (w) */
	volatile u32 clear;	/* +0x20 (w) */
	volatile u32 txq;	/* +0x24 (r/w) */
	volatile u32 rxq;	/* +0x28 (r) */
	volatile u32 fifo_p;	/* +0x2c (r) */
	volatile u32 cycle2;	/* +0x30 (r/w) */
};

struct audio_stream {
	char *id;		/* identification string */
	int dma_ch;
	dma_regs_t *dma_regs;	/* points to our DMA registers */
	dma_addr_t phys_xq;	/* PCM Data buffer address */
	u32 txrx_id;		/* stream id and PCM enable bit */
	volatile u32 *txrx_en;	/* PCM enable register */
	volatile u32 *txrx_dis;	/* PCM disable register */
#ifdef MP200_PCM_INTERRUPT_ENABLE
	volatile u32 *func_sel;	/* PCM func register */
#endif
	int active:1;		/* we are using this stream for transfer now */
	int period;		/* current transfer period */
	int periods;		/* current count of periods registerd in the DMA engine */
	int add_period;		/* add transfer period */
	int tx_spin;		/* are we recoding - flag used to do DMA trans. for sync */
	unsigned int old_offset;
	spinlock_t dma_lock;	/* for locking in DMA operations (see dma-sa1100.c in the kernel) */

	struct snd_pcm_substream *stream;
};

struct mp200_pcm_client {
	struct audio_stream* s[2];
	int pcm_ch;
	struct pcm_regs *pcm_regs;	/* points to our PCM registers */
	pcm_ctrl_t *sett;
	int (*startup)(struct snd_pcm_substream *);
	void (*shutdown)(struct snd_pcm_substream *);
	int (*prepare)(struct snd_pcm_substream *);
};

extern int mp200_pcm_new(struct snd_card *, struct mp200_pcm_client *, struct snd_pcm **);
extern int mp200_pcm_free(struct mp200_pcm_client *);
extern int mp200_pcm_set_ctrl(struct pcm_regs *, pcm_ctrl_t *);
#ifdef CONFIG_PM
extern int mp200_pcm_suspend(struct platform_device *, pm_message_t);
extern int mp200_pcm_resume(struct platform_device *);
#endif

#ifdef AUDIO_MAKING_DEBUG
extern int debug;
#endif

