mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2025-04-21 12:27:27 +03:00
jz4740: new dma api. cleanup audio pcm module
This commit is contained in:
@@ -15,251 +15,75 @@
|
||||
#ifndef __ASM_JZ4740_DMA_H__
|
||||
#define __ASM_JZ4740_DMA_H__
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/io.h> /* need byte IO */
|
||||
#include <linux/spinlock.h> /* And spinlocks */
|
||||
#include <linux/delay.h>
|
||||
#include <asm/mach-jz4740/regs.h>
|
||||
#include <asm/mach-jz4740/ops.h>
|
||||
struct jz4740_dma_chan;
|
||||
|
||||
/*
|
||||
* Descriptor structure for JZ4740 DMA engine
|
||||
* Note: this structure must always be aligned to a 16-bytes boundary.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
volatile u32 dcmd; /* DCMD value for the current transfer */
|
||||
volatile u32 dsadr; /* DSAR value for the current transfer */
|
||||
volatile u32 dtadr; /* DTAR value for the current transfer */
|
||||
volatile u32 ddadr; /* Points to the next descriptor + transfer count */
|
||||
} jz_dma_desc;
|
||||
|
||||
|
||||
/* DMA Device ID's follow */
|
||||
enum {
|
||||
DMA_ID_UART0_TX = 0,
|
||||
DMA_ID_UART0_RX,
|
||||
DMA_ID_SSI_TX,
|
||||
DMA_ID_SSI_RX,
|
||||
DMA_ID_AIC_TX,
|
||||
DMA_ID_AIC_RX,
|
||||
DMA_ID_MSC_TX,
|
||||
DMA_ID_MSC_RX,
|
||||
DMA_ID_TCU_OVERFLOW,
|
||||
DMA_ID_AUTO,
|
||||
DMA_ID_RAW_SET,
|
||||
DMA_ID_MAX
|
||||
enum jz4740_dma_request_type {
|
||||
JZ4740_DMA_TYPE_AUTO_REQUEST = 8,
|
||||
JZ4740_DMA_TYPE_UART_TRANSMIT = 20,
|
||||
JZ4740_DMA_TYPE_UART_RECEIVE = 21,
|
||||
JZ4740_DMA_TYPE_SPI_TRANSMIT = 22,
|
||||
JZ4740_DMA_TYPE_SPI_RECEIVE = 23,
|
||||
JZ4740_DMA_TYPE_AIC_TRANSMIT = 24,
|
||||
JZ4740_DMA_TYPE_AIC_RECEIVE = 25,
|
||||
JZ4740_DMA_TYPE_MMC_TRANSMIT = 26,
|
||||
JZ4740_DMA_TYPE_MMC_RECEIVE = 27,
|
||||
JZ4740_DMA_TYPE_TCU = 28,
|
||||
JZ4740_DMA_TYPE_SADC = 29,
|
||||
JZ4740_DMA_TYPE_SLCD = 30,
|
||||
};
|
||||
|
||||
/* DMA modes, simulated by sw */
|
||||
#define DMA_MODE_READ 0x0 /* I/O to memory, no autoinit, increment, single mode */
|
||||
#define DMA_MODE_WRITE 0x1 /* memory to I/O, no autoinit, increment, single mode */
|
||||
#define DMA_AUTOINIT 0x2
|
||||
#define DMA_MODE_MASK 0x3
|
||||
|
||||
struct jz_dma_chan {
|
||||
int dev_id; /* DMA ID: this channel is allocated if >=0, free otherwise */
|
||||
unsigned int io; /* DMA channel number */
|
||||
const char *dev_str; /* string describes the DMA channel */
|
||||
int irq; /* DMA irq number */
|
||||
void *irq_dev; /* DMA private device structure */
|
||||
unsigned int fifo_addr; /* physical fifo address of the requested device */
|
||||
unsigned int cntl; /* DMA controll */
|
||||
unsigned int mode; /* DMA configuration */
|
||||
unsigned int source; /* DMA request source */
|
||||
enum jz4740_dma_width {
|
||||
JZ4740_DMA_WIDTH_8BIT,
|
||||
JZ4740_DMA_WIDTH_16BIT,
|
||||
JZ4740_DMA_WIDTH_32BIT,
|
||||
};
|
||||
|
||||
extern struct jz_dma_chan jz_dma_table[];
|
||||
enum jz4740_dma_transfer_size {
|
||||
JZ4740_DMA_TRANSFER_SIZE_4BYTE = 0,
|
||||
JZ4740_DMA_TRANSFER_SIZE_1BYTE = 1,
|
||||
JZ4740_DMA_TRANSFER_SIZE_2BYTE = 2,
|
||||
JZ4740_DMA_TRANSFER_SIZE_16BYTE = 3,
|
||||
JZ4740_DMA_TRANSFER_SIZE_32BYTE = 4,
|
||||
};
|
||||
|
||||
enum jz4740_dma_flags {
|
||||
JZ4740_DMA_SRC_AUTOINC = 0x2,
|
||||
JZ4740_DMA_DST_AUTOINC = 0x1,
|
||||
};
|
||||
|
||||
enum jz4740_dma_mode {
|
||||
JZ4740_DMA_MODE_SINGLE = 0,
|
||||
JZ4740_DMA_MODE_BLOCK = 1,
|
||||
};
|
||||
|
||||
struct jz4740_dma_config {
|
||||
enum jz4740_dma_width src_width;
|
||||
enum jz4740_dma_width dst_width;
|
||||
enum jz4740_dma_transfer_size transfer_size;
|
||||
enum jz4740_dma_request_type request_type;
|
||||
enum jz4740_dma_flags flags;
|
||||
enum jz4740_dma_mode mode;
|
||||
};
|
||||
|
||||
typedef void (*jz4740_dma_complete_callback_t)(struct jz4740_dma_chan *, int , void *);
|
||||
|
||||
struct jz4740_dma_chan* jz4740_dma_request(void *dev, const char *name);
|
||||
void jz4740_dma_free(struct jz4740_dma_chan *dma);
|
||||
|
||||
void jz4740_dma_configure(struct jz4740_dma_chan *dma,
|
||||
const struct jz4740_dma_config *config);
|
||||
|
||||
|
||||
#define DMA_8BIT_RX_CMD \
|
||||
DMAC_DCMD_DAI | \
|
||||
DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \
|
||||
DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN
|
||||
void jz4740_dma_enable(struct jz4740_dma_chan *dma);
|
||||
void jz4740_dma_disable(struct jz4740_dma_chan *dma);
|
||||
|
||||
#define DMA_8BIT_TX_CMD \
|
||||
DMAC_DCMD_SAI | \
|
||||
DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \
|
||||
DMAC_DCMD_DS_8BIT | DMAC_DCMD_RDIL_IGN
|
||||
void jz4740_dma_set_src_addr(struct jz4740_dma_chan *dma, dma_addr_t src);
|
||||
void jz4740_dma_set_dst_addr(struct jz4740_dma_chan *dma, dma_addr_t dst);
|
||||
void jz4740_dma_set_transfer_count(struct jz4740_dma_chan *dma, uint32_t count);
|
||||
|
||||
#define DMA_16BIT_RX_CMD \
|
||||
DMAC_DCMD_DAI | \
|
||||
DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_32 | \
|
||||
DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN
|
||||
uint32_t jz4740_dma_get_residue(const struct jz4740_dma_chan *dma);
|
||||
|
||||
#define DMA_16BIT_TX_CMD \
|
||||
DMAC_DCMD_SAI | \
|
||||
DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_16 | \
|
||||
DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN
|
||||
|
||||
#define DMA_32BIT_RX_CMD \
|
||||
DMAC_DCMD_DAI | \
|
||||
DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \
|
||||
DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN
|
||||
|
||||
#define DMA_32BIT_TX_CMD \
|
||||
DMAC_DCMD_SAI | \
|
||||
DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \
|
||||
DMAC_DCMD_DS_32BIT | DMAC_DCMD_RDIL_IGN
|
||||
|
||||
#define DMA_16BYTE_RX_CMD \
|
||||
DMAC_DCMD_DAI | \
|
||||
DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \
|
||||
DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN
|
||||
|
||||
#define DMA_16BYTE_TX_CMD \
|
||||
DMAC_DCMD_SAI | \
|
||||
DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \
|
||||
DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN
|
||||
|
||||
#define DMA_32BYTE_RX_CMD \
|
||||
DMAC_DCMD_DAI | \
|
||||
DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_32 | \
|
||||
DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN
|
||||
|
||||
#define DMA_32BYTE_TX_CMD \
|
||||
DMAC_DCMD_SAI | \
|
||||
DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_8 | \
|
||||
DMAC_DCMD_DS_32BYTE | DMAC_DCMD_RDIL_IGN
|
||||
|
||||
#define DMA_AIC_32_16BYTE_TX_CMD \
|
||||
DMAC_DCMD_SAI | \
|
||||
DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \
|
||||
DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN
|
||||
|
||||
#define DMA_AIC_32_16BYTE_RX_CMD \
|
||||
DMAC_DCMD_DAI | \
|
||||
DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \
|
||||
DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN
|
||||
|
||||
#define DMA_AIC_16BIT_TX_CMD \
|
||||
DMAC_DCMD_SAI | \
|
||||
DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \
|
||||
DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN
|
||||
|
||||
#define DMA_AIC_16BIT_RX_CMD \
|
||||
DMAC_DCMD_DAI | \
|
||||
DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \
|
||||
DMAC_DCMD_DS_16BIT | DMAC_DCMD_RDIL_IGN
|
||||
|
||||
#define DMA_AIC_16BYTE_RX_CMD \
|
||||
DMAC_DCMD_DAI | \
|
||||
DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \
|
||||
DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN
|
||||
|
||||
#define DMA_AIC_16BYTE_TX_CMD \
|
||||
DMAC_DCMD_SAI | \
|
||||
DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \
|
||||
DMAC_DCMD_DS_16BYTE | DMAC_DCMD_RDIL_IGN
|
||||
|
||||
extern int jz_request_dma(int dev_id,
|
||||
const char *dev_str,
|
||||
irqreturn_t (*irqhandler)(int, void *),
|
||||
unsigned long irqflags,
|
||||
void *irq_dev_id);
|
||||
extern void jz_free_dma(unsigned int dmanr);
|
||||
|
||||
extern int jz_dma_read_proc(char *buf, char **start, off_t fpos,
|
||||
int length, int *eof, void *data);
|
||||
extern void dump_jz_dma_channel(unsigned int dmanr);
|
||||
|
||||
extern void enable_dma(unsigned int dmanr);
|
||||
extern void disable_dma(unsigned int dmanr);
|
||||
extern void set_dma_addr(unsigned int dmanr, unsigned int phyaddr);
|
||||
extern void set_dma_count(unsigned int dmanr, unsigned int bytecnt);
|
||||
extern void set_dma_mode(unsigned int dmanr, unsigned int mode);
|
||||
extern void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt);
|
||||
extern unsigned int get_dma_residue(unsigned int dmanr);
|
||||
|
||||
extern spinlock_t dma_spin_lock;
|
||||
|
||||
static __inline__ unsigned long claim_dma_lock(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&dma_spin_lock, flags);
|
||||
return flags;
|
||||
}
|
||||
|
||||
static __inline__ void release_dma_lock(unsigned long flags)
|
||||
{
|
||||
spin_unlock_irqrestore(&dma_spin_lock, flags);
|
||||
}
|
||||
|
||||
/* Clear the 'DMA Pointer Flip Flop'.
|
||||
* Write 0 for LSB/MSB, 1 for MSB/LSB access.
|
||||
*/
|
||||
#define clear_dma_ff(channel)
|
||||
|
||||
static __inline__ struct jz_dma_chan *get_dma_chan(unsigned int dmanr)
|
||||
{
|
||||
if (dmanr > MAX_DMA_NUM
|
||||
|| jz_dma_table[dmanr].dev_id < 0)
|
||||
return NULL;
|
||||
return &jz_dma_table[dmanr];
|
||||
}
|
||||
|
||||
static __inline__ int dma_halted(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return 1;
|
||||
return __dmac_channel_transmit_halt_detected(dmanr) ? 1 : 0;
|
||||
}
|
||||
|
||||
static __inline__ unsigned int get_dma_mode(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return 0;
|
||||
return chan->mode;
|
||||
}
|
||||
|
||||
static __inline__ void clear_dma_done(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return;
|
||||
REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR);
|
||||
}
|
||||
|
||||
static __inline__ void clear_dma_halt(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return;
|
||||
REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT);
|
||||
REG_DMAC_DMACR &= ~(DMAC_DMACR_HLT);
|
||||
}
|
||||
|
||||
static __inline__ void clear_dma_flag(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return;
|
||||
REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR);
|
||||
REG_DMAC_DMACR &= ~(DMAC_DMACR_HLT | DMAC_DMACR_AR);
|
||||
}
|
||||
|
||||
static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
|
||||
{
|
||||
}
|
||||
|
||||
static __inline__ unsigned int get_dma_done_status(unsigned int dmanr)
|
||||
{
|
||||
unsigned long dccsr;
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return 0;
|
||||
dccsr = REG_DMAC_DCCSR(chan->io);
|
||||
return dccsr & (DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR);
|
||||
}
|
||||
|
||||
static __inline__ int get_dma_done_irq(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return -1;
|
||||
return chan->irq;
|
||||
}
|
||||
void jz4740_dma_set_complete_cb(struct jz4740_dma_chan *dma,
|
||||
jz4740_dma_complete_callback_t cb);
|
||||
|
||||
#endif /* __ASM_JZ4740_DMA_H__ */
|
||||
|
||||
Reference in New Issue
Block a user