📄 hw_hdmactrl.c
字号:
/****************************************************************
Copyright (C) 2007 RockChip All Rights Reserved.
File: HDMACtrl.c
Desc: HDMA control
Author:LingZJ
Date: 2007/06/30
note:
$Log: HW_HDMACtrl.c,v $
Revision 1.2 2008/06/19 04:43:31 Administrator
代码整理!
Revision 1.1.1.1 2008/05/07 04:15:08 Administrator
no message
Revision 1.1.1.1 2008/03/06 13:29:05 Lingzhaojun
no message
Revision 1.6 2007/11/10 04:24:48 Huangxinyu
调试修改
Revision 1.5 2007/10/24 07:21:01 Hanjiang
no message
Revision 1.4 2007/10/23 08:23:14 Huangxinyu
调试后修改bug
Revision 1.3 2007/10/15 09:07:59 Huangxinyu
根据RK27提交修改driver
Revision 1.2 2007/10/08 02:38:43 Lingzhaojun
添加版本自动注释脚本
Revision 1.1.1.1 2007/09/27 09:06:00 cvsadmin
no message
Revision 1.4 2007/09/24 04:00:00 Lingzhaojun
提交驱动、FM、打包目录分离相关代码
1.2007-06-29,LingZJ,创建文件
2.2007-06-30,LingZJ,整理程序和变量,常量。
3.2007-08-16, lzy 整理程序和变量
4.2008-8-30, lzy 整理程序和变量
*****************************************************************/
#include "hw_include.h"
#include "HW_HDMACtrl.h"
#include "HW_I2sCtrl.h"
static DMACallBack DmaCallBack[2] = {NULL, NULL};
/*---------------------------------------------------------
Name : DMAIntrHandler
Desc : HDMA中断服务程序
Params:
Author: LingZJ
Date : 070630
lzy modified @ 8-30
-----------------------------------------------------------*/
static void HDMA_isr(void)
{
unsigned int IntState, channel;
DMACallBack callback;
IntState = HW_HdmaGetIntrState();
WriteReg32(RegHDMA_ISR, ReadReg32(RegHDMA_ISR)&(~(0x3f)));
for (channel = 0; channel < 0x2; channel++)
{
if (IntState&((0x15) << channel))
{
if (DmaCallBack[channel])
{
callback = DmaCallBack[channel];
DmaCallBack[channel] = NULL;
callback();
}
}
}
}
/*---------------------------------------------------------
Name : DmaTransmit
Desc : 启用DMA传送
Params: SrcAddr:源地址
DestinAddr: 目的地址,长度
Mode :传送模式
CallBack:传输完成回调函数
Return: 状态
Author: Lzj create, lzy modify
Date : 070830
Note: count 为传输的数据大小,对应传输宽度
burst 为总线burst 的大小,最好和count 为倍数关系
驱动中自动对burst 进行优化,16倍数的传输效率最高
最大传输数量为64K * 数据宽度
-----------------------------------------------------------*/
int DmaTransmit(HDMA_Channel_t channel, UINT32 SrcAddr, UINT32 DestinAddr, UINT32 Count, UINT32 Mode, DMACallBack CallBack)
{
unsigned int mode = 0; /*通道*/
if (HW_HdmaGetReadyState() == 0x01)
return DmaBusy;
if (HW_HdmaGetDMAState(channel))
return DmaBusy;
//Set Address and size
HW_HdmaSourceAddr(channel, TransVAtoPA(SrcAddr));
HW_HdmaDestinatAddr(channel, TransVAtoPA(DestinAddr));
// HDMA terminal count is to zero, so must minus 1;
HW_HdmaSetCount(channel, Count - 1);
if (CallBack)
{
mode |= DmaMode_Interrupt;
DmaCallBack[channel] = CallBack;
Intr_Enable(INTC_HDMA);
}
//start the DMA transfer
if (Mode&DmaMode_Hard)
{
// I2s dam transmit is always burst8
mode |= Mode & (DmaMode_RequestMask
| DmaMode_SrmodeMask
| DmaMode_DrmodeMask
| DmaMode_WidthMask
| DmaMode_HWMask);
HW_HdmaSliceCount(channel, 7);
HW_HdmaPageNumber(channel, 1);
mode |= DmaMode_Slice | DMA_CHN_EN | DmaMode_Hard | DmaMode_Burst8;
WriteReg32(RegHDMA_CON(channel), mode);
}
else
{
if ((Count % 16) == 0)
mode |= DmaMode_Burst16;
else if ((Count % 8) == 0)
mode |= DmaMode_Burst8;
else if ((Count % 4) == 0)
mode |= DmaMode_Burst4;
else
mode |= DmaMode_BurstSignle;
mode |= Mode & (DmaMode_SrmodeMask
| DmaMode_DrmodeMask
| DmaMode_WidthMask
| DmaMode_HWMask);
mode |= DmaMode_SoftwareStar | DMA_CHN_EN;
WriteReg32(RegHDMA_CON(channel), mode);
}
return channel;
}
/**************************************************************************
* 函数描述: HDMA 读通道状态
* 入口参数: 无
* 出口参数: 无
* 返回值: 无
* 注释: 采用查询方式使用DMA 时通过此接口判断传输状态
***************************************************************************/
int HDMA_GetStatus(HDMA_Channel_t channel)
{
if (ReadReg32(RegHDMA_DSR)&(0x01 << channel))
return DmaBusy;
else
return DmaSuccess;
}
/**************************************************************************
* 函数描述: HDMA 开机初始化程序
* 入口参数: 无
* 出口参数: 无
* 返回值: 无
* 注释: 启用HDMA 时调用
***************************************************************************/
void HDMA_PowerOnInit(void)
{
int temp, channel;
Scu_ClockEnable(HDMA_CLOCK);
for (channel = 0; channel < HDMA_chnmax; channel++)
{
// clear page count number and disable page function
HW_HdmaClearCPNCNTD(channel);
// cancel software DMA operation
temp = ReadReg32(RegHDMA_CON(channel));
temp = (temp & ~HDMAMode_SwcMask) | HDMAMode_SoftStop;
WriteReg32(RegHDMA_CON(channel), temp);
// clear dma config register
WriteReg32(RegHDMA_CON(channel), 0x00); //ReadReg32(RegA2A_CON(0))|A2AMode_SoftStop);
}
// clear DMA interrupt
WriteReg32(RegHDMA_ISR, 0x00);
Intr_RegISR(INTC_HDMA, HDMA_isr);
}
/**************************************************************************
* 函数描述: HDMA 反初始化函数
* 入口参数: 无
* 出口参数: 无
* 返回值: 无
* 注释: 关闭HDMA 时调用
***************************************************************************/
void HDMA_DeInit(void)
{
WriteReg32(RegHDMA_ISR, 0x00);
Intr_RegISR(INTC_HDMA, NULL);
Intr_Disable(INTC_HDMA);
Scu_ClockDisable(HDMA_CLOCK);
}
/**************************************************************************
* 函数描述: HDMA 反初始化函数
* 入口参数: 无
* 出口参数: 无
* 返回值: 无
* 注释: 关闭HDMA 时调用
***************************************************************************/
void HDMA_Stop(HDMA_Channel_t channel)
{
int temp;
channel = 0;
HW_HdmaClearCPNCNTD(channel);
// cancel software DMA operation
temp = ReadReg32(RegHDMA_CON(channel));
temp = (temp & ~HDMAMode_SwcMask) | HDMAMode_SoftStop;
WriteReg32(RegHDMA_CON(channel), temp);
// clear dma config register
WriteReg32(RegHDMA_CON(channel), 0x00); //ReadReg32(RegA2A_CON(0))|A2AMode_SoftStop);
WriteReg32(RegHDMA_ISR, 0x00);
// Intr_RegISR(INTC_HDMA, NULL);
// Intr_Disable(INTC_HDMA);
}
#if 0
/**************************************************************************
* 函数描述: HDMA 反初始化函数
* 入口参数: 无
* 出口参数: 无
* 返回值: 无
* 注释: 关闭HDMA 时调用
***************************************************************************/
int DMA_AudioOut(UINT32 SrcAddr, UINT32 bufsize, UINT32 bufnumber, DMACallBack CallBack)
{
unsigned int mode;
unsigned int channel = 1;
HW_HdmaDisable(channel);
HW_HdmaSourceAddr(channel, TransVAtoPA(SrcAddr));
HW_HdmaDestinatAddr(channel, TransVAtoPA(RegI2s_TXR));
// HDMA terminal count is to zero, so must minus 1;
HW_HdmaSetCount(channel, bufsize - 1);
HW_HdmaClearCPNCNTD(channel);
mode = DmaMode_Slice
| DmaMode_Hard
| DmaMode_width32Bit
| DmaMode_DestFix
| DmaMode_SourceInc
| DmaMode_Request16
| DmaMode_Burst16
| DmaMode_Interrupt;
//
WriteReg32(RegHDMA_CON(channel), mode);
// slice is half of I2S FIFO size, so there is fixed to 16
HW_HdmaSliceCount(channel, 16);
HW_HdmaPageNumber(channel, bufnumber);
// buffer size is byte count, so must *2
// HW_HdmaSrcBufSize(channel, bufsize*bufnumber*2);
DmaCallBack[channel] = CallBack;
Intr_Enable(INTC_HDMA);
mode |= DmaMode_Enable | DmaMode_HWEnable;
WriteReg32(RegHDMA_CON(channel), mode);
return TRUE;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -